template<class TAAPos> inline void TransformVertex(Vertex* vrt, matrix33& m, TAAPos& aaPos) { // todo: avoid unnecessary copy vector3 oldPos = aaPos[vrt]; MatVecMult(aaPos[vrt], m, oldPos); }
void ConvectionDiffusionFE<TDomain>:: add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[]) { // request geometry const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder); number integrand, shape_u; MathMatrix<dim,dim> D; MathVector<dim> v, Dgrad_u, grad_u; // loop integration points for(size_t ip = 0; ip < geo.num_ip(); ++ip) { // get current u and grad_u VecSet(grad_u, 0.0); shape_u = 0.0; for(size_t j = 0; j < geo.num_sh(); ++j) { VecScaleAppend(grad_u, u(_C_,j), geo.global_grad(ip, j)); shape_u += u(_C_,j) * geo.shape(ip, j); } // Diffusion if(m_imDiffusion.data_given()) MatVecMult(Dgrad_u, m_imDiffusion[ip], grad_u); else VecSet(Dgrad_u, 0.0); // Convection if(m_imVelocity.data_given()) VecScaleAppend(Dgrad_u, -1*shape_u, m_imVelocity[ip]); // Convection if(m_imFlux.data_given()) VecScaleAppend(Dgrad_u, 1.0, m_imFlux[ip]); // loop test spaces for(size_t i = 0; i < geo.num_sh(); ++i) { // compute integrand integrand = VecDot(Dgrad_u, geo.global_grad(ip, i)); // add Reaction Rate if(m_imReactionRate.data_given()) integrand += m_imReactionRate[ip] * shape_u * geo.shape(ip, i); // add Reaction if(m_imReaction.data_given()) integrand += m_imReaction[ip] * geo.shape(ip, i); // multiply by integration weight integrand *= geo.weight(ip); // add to local defect d(_C_, i) += integrand; } } }
inline void OrthogProjectVec (vector_t& v, const matrix_t& A) { typedef typename matrix_t::size_type size_type; typedef typename matrix_t::value_type value_type; // I. Solve the least square problem: matrix_t M = A; // we do not work with the original matrix; otherwise it would be destroyed InvMatVecMult_byGivens (M, v); // II. Compute the linear combination of the columns: MathVector<matrix_t::ColSize, value_type> coeff; for (size_type i = 0; i < matrix_t::ColSize; i++) coeff [i] = v [i]; MatVecMult (v, A, coeff); }
void ConvectionDiffusionFE<TDomain>:: add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[]) { // request geometry const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder); MathVector<dim> v, Dgrad; // loop integration points for(size_t ip = 0; ip < geo.num_ip(); ++ip) { // loop trial space for(size_t j = 0; j < geo.num_sh(); ++j) { // Diffusion if(m_imDiffusion.data_given()) MatVecMult(Dgrad, m_imDiffusion[ip], geo.global_grad(ip, j)); else VecSet(Dgrad, 0.0); // Convection if(m_imVelocity.data_given()) VecScaleAppend(Dgrad, -1*geo.shape(ip,j), m_imVelocity[ip]); // no explicit dependency on m_imFlux // loop test space for(size_t i = 0; i < geo.num_sh(); ++i) { // compute integrand number integrand = VecDot(Dgrad, geo.global_grad(ip, i)); // Reaction if(m_imReactionRate.data_given()) integrand += m_imReactionRate[ip] * geo.shape(ip, j) * geo.shape(ip, i); // no explicit dependency on m_imReaction // multiply by weight integrand *= geo.weight(ip); // add to local matrix J(_C_, i, _C_, j) += integrand; } } } }
void OGL_ModelData::Load() { // Already loaded? if (ModelPresent()) { return; } // Load the model Model.Clear(); if (ModelFile == FileSpecifier()) { return; } if (!ModelFile.Exists()) { return; } bool Success = false; char *Type = &ModelType[0]; if (StringsEqual(Type,"wave",4)) { // Alias|Wavefront Success = LoadModel_Wavefront(ModelFile, Model); } else if (StringsEqual(Type,"3ds",3)) { // 3D Studio Max Success = LoadModel_Studio(ModelFile, Model); } else if (StringsEqual(Type,"dim3",4)) { // Brian Barnes's "Dim3" model format (first pass: model geometry) Success = LoadModel_Dim3(ModelFile, Model, LoadModelDim3_First); // Second and third passes: frames and sequences try { if (ModelFile1 == FileSpecifier()) { throw 0; } if (!ModelFile1.Exists()) { throw 0; } if (!LoadModel_Dim3(ModelFile1, Model, LoadModelDim3_Rest)) { throw 0; } } catch(...) {} // try { if (ModelFile2 == FileSpecifier()) { throw 0; } if (!ModelFile2.Exists()) { throw 0; } if (!LoadModel_Dim3(ModelFile2, Model, LoadModelDim3_Rest)) { throw 0; } } catch(...) {} } #if HAVE_QUESA else if (StringsEqual(Type, "qd3d") || StringsEqual(Type,"3dmf") || StringsEqual(Type,"quesa")) { // QuickDraw 3D / Quesa Success = LoadModel_QD3D(ModelFile, Model); } #endif if (!Success) { Model.Clear(); return; } // Calculate transformation matrix GLfloat Angle, Cosine, Sine; GLfloat RotMatrix[3][3], NewRotMatrix[3][3], IndivRotMatrix[3][3]; MatIdentity(RotMatrix); MatIdentity(IndivRotMatrix); Angle = (float)Degree2Radian*XRot; Cosine = (float)cos(Angle); Sine = (float)sin(Angle); IndivRotMatrix[1][1] = Cosine; IndivRotMatrix[1][2] = -Sine; IndivRotMatrix[2][1] = Sine; IndivRotMatrix[2][2] = Cosine; MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix); MatCopy(NewRotMatrix,RotMatrix); MatIdentity(IndivRotMatrix); Angle = (float)Degree2Radian*YRot; Cosine = (float)cos(Angle); Sine = (float)sin(Angle); IndivRotMatrix[2][2] = Cosine; IndivRotMatrix[2][0] = -Sine; IndivRotMatrix[0][2] = Sine; IndivRotMatrix[0][0] = Cosine; MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix); MatCopy(NewRotMatrix,RotMatrix); MatIdentity(IndivRotMatrix); Angle = (float)Degree2Radian*ZRot; Cosine = (float)cos(Angle); Sine = (float)sin(Angle); IndivRotMatrix[0][0] = Cosine; IndivRotMatrix[0][1] = -Sine; IndivRotMatrix[1][0] = Sine; IndivRotMatrix[1][1] = Cosine; MatMult(IndivRotMatrix,RotMatrix,NewRotMatrix); MatCopy(NewRotMatrix,RotMatrix); MatScalMult(NewRotMatrix,Scale); // For the position vertices if (Scale < 0) { MatScalMult(RotMatrix,-1); // For the normals } // Is model animated or static? // Test by trying to find neutral positions (useful for working with the normals later on) if (Model.FindPositions_Neutral(false)) { // Copy over the vector and normal transformation matrices: for (int k=0; k<3; k++) for (int l=0; l<3; l++) { Model.TransformPos.M[k][l] = NewRotMatrix[k][l]; Model.TransformNorm.M[k][l] = RotMatrix[k][l]; } Model.TransformPos.M[0][3] = XShift; Model.TransformPos.M[1][3] = YShift; Model.TransformPos.M[2][3] = ZShift; // Find the transformed bounding box: bool RestOfCorners = false; GLfloat NewBoundingBox[2][3]; // The indices i1, i2, and i3 are for selecting which of the box's two principal corners // to get coordinates from for (int i1=0; i1<2; i1++) { GLfloat X = Model.BoundingBox[i1][0]; for (int i2=0; i2<2; i2++) { GLfloat Y = Model.BoundingBox[i2][0]; for (int i3=0; i3<2; i3++) { GLfloat Z = Model.BoundingBox[i3][0]; GLfloat Corner[3]; for (int ic=0; ic<3; ic++) { GLfloat *Row = Model.TransformPos.M[ic]; Corner[ic] = Row[0]*X + Row[1]*Y + Row[2]*Z + Row[3]; } if (RestOfCorners) { // Find minimum and maximum for each coordinate for (int ic=0; ic<3; ic++) { NewBoundingBox[0][ic] = min(NewBoundingBox[0][ic],Corner[ic]); NewBoundingBox[1][ic] = max(NewBoundingBox[1][ic],Corner[ic]); } } else { // Simply copy it in: for (int ic=0; ic<3; ic++) NewBoundingBox[0][ic] = NewBoundingBox[1][ic] = Corner[ic]; RestOfCorners = true; } } } } for (int ic=0; ic<2; ic++) objlist_copy(Model.BoundingBox[ic],NewBoundingBox[ic],3); } else { // Static model size_t NumVerts = Model.Positions.size()/3; for (size_t k=0; k<NumVerts; k++) { GLfloat *Pos = Model.PosBase() + 3*k; GLfloat NewPos[3]; MatVecMult(NewRotMatrix,Pos,NewPos); // Has the scaling Pos[0] = NewPos[0] + XShift; Pos[1] = NewPos[1] + YShift; Pos[2] = NewPos[2] + ZShift; } size_t NumNorms = Model.Normals.size()/3; for (size_t k=0; k<NumNorms; k++) { GLfloat *Norms = Model.NormBase() + 3*k; GLfloat NewNorms[3]; MatVecMult(RotMatrix,Norms,NewNorms); // Not scaled objlist_copy(Norms,NewNorms,3); } // So as to be consistent with the new points Model.FindBoundingBox(); } Model.AdjustNormals(NormalType,NormalSplit); Model.CalculateTangents(); // Don't forget the skins OGL_SkinManager::Load(); }
void ConvectionDiffusionFVCR<TDomain>:: ex_grad(MathVector<dim> 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<MathVector<dim> > > 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; // reference dimension static const int refDim = ref_elem_type::dim; // 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); VecSet(vValue[ip], 0.0); for(size_t sh = 0; sh < scvf.num_sh(); ++sh) VecScaleAppend(vValue[ip], u(_C_, sh), scvf.global_grad(sh)); if(bDeriv) for(size_t sh = 0; sh < scvf.num_sh(); ++sh) vvvDeriv[ip][_C_][sh] = scvf.global_grad(sh); } } // general case else { // get trial space LagrangeP1<ref_elem_type>& rTrialSpace = Provider<LagrangeP1<ref_elem_type> >::get(); // storage for shape function at ip MathVector<refDim> vLocGrad[numSH]; MathVector<refDim> locGrad; // Reference Mapping MathMatrix<dim, refDim> JTInv; ReferenceMapping<ref_elem_type, dim> mapping(vCornerCoords); // loop ips for(size_t ip = 0; ip < nip; ++ip) { // evaluate at shapes at ip rTrialSpace.grads(vLocGrad, vLocIP[ip]); // compute grad at ip VecSet(locGrad, 0.0); for(size_t sh = 0; sh < numSH; ++sh) VecScaleAppend(locGrad, u(_C_, sh), vLocGrad[sh]); // compute global grad mapping.jacobian_transposed_inverse(JTInv, vLocIP[ip]); MatVecMult(vValue[ip], JTInv, locGrad); // compute derivative w.r.t. to unknowns iff needed if(bDeriv) for(size_t sh = 0; sh < numSH; ++sh) MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]); } } };
void ConvectionDiffusionFVCR<TDomain>:: add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[]) { // get finite volume geometry static const TFVGeom& geo = GeomProvider<TFVGeom>::get(); // get conv shapes // const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo); if(m_imDiffusion.data_given() || m_imVelocity.data_given()) { // 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); ///////////////////////////////////////////////////// // Diffusive Term ///////////////////////////////////////////////////// if(m_imDiffusion.data_given()) { // to compute D \nabla c MathVector<dim> Dgrad_c, grad_c; // compute gradient and shape at ip VecSet(grad_c, 0.0); for(size_t sh = 0; sh < scvf.num_sh(); ++sh) VecScaleAppend(grad_c, u(_C_,sh), scvf.global_grad(sh)); // scale by diffusion tensor MatVecMult(Dgrad_c, m_imDiffusion[ip], grad_c); // Compute flux const number diff_flux = VecDot(Dgrad_c, scvf.normal()); // Add to local defect d(_C_, scvf.from()) -= diff_flux; d(_C_, scvf.to() ) += diff_flux; } ///////////////////////////////////////////////////// // Convective Term ///////////////////////////////////////////////////// /* if(m_imVelocity.data_given()) { // sum up convective flux using convection shapes number conv_flux = 0.0; for(size_t sh = 0; sh < convShape.num_sh(); ++sh) conv_flux += u(_C_, sh) * convShape(ip, sh); // add to local defect d(_C_, scvf.from()) += conv_flux; d(_C_, scvf.to() ) -= conv_flux; }*/ } } // reaction rate if(m_imReactionRate.data_given()) { // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) { // get current SCV const typename TFVGeom::SCV& scv = geo.scv(ip); // get associated node const int co = scv.node_id(); // Add to local defect d(_C_, co) += u(_C_, co) * m_imReactionRate[ip] * scv.volume(); } } // reaction rate if(m_imReaction.data_given()) { // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) { // get current SCV const typename TFVGeom::SCV& scv = geo.scv(ip); // get associated node const int co = scv.node_id(); // Add to local defect d(_C_, co) += m_imReaction[ip] * scv.volume(); } } // handle constrained dofs, compute defect of interpolation equation if(TFVGeom::usesHangingNodes){ for (size_t i=0;i<geo.num_constrained_dofs();i++){ const typename TFVGeom::CONSTRAINED_DOF& cd = geo.constrained_dof(i); const size_t index = cd.index(); number defect = u(_C_,index); for (size_t j=0;j<cd.num_constraining_dofs();j++) defect -= cd.constraining_dofs_weight(j) * u(_C_,cd.constraining_dofs_index(j)); d(_C_,index) = defect; } } }
void ConvectionDiffusionFVCR<TDomain>:: add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[]) { // get finite volume geometry static const TFVGeom& geo = GeomProvider<TFVGeom>::get(); // Diff. Tensor times Gradient MathVector<dim> Dgrad; // get conv shapes // const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo); // Diffusion and Velocity Term if(m_imDiffusion.data_given() || m_imVelocity.data_given()) { // 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); //////////////////////////////////////////////////// // Diffusive Term //////////////////////////////////////////////////// if(m_imDiffusion.data_given()) { // loop shape functions for(size_t sh = 0; sh < scvf.num_sh(); ++sh) { // Compute Diffusion Tensor times Gradient MatVecMult(Dgrad, m_imDiffusion[ip], scvf.global_grad(sh)); // Compute flux at IP const number D_diff_flux = VecDot(Dgrad, scvf.normal()); // Add flux term to local matrix J(_C_, scvf.from(), _C_, sh) -= D_diff_flux; J(_C_, scvf.to() , _C_, sh) += D_diff_flux; } } //////////////////////////////////////////////////// // Convective Term //////////////////////////////////////////////////// /* if(m_imVelocity.data_given()) { // Add Flux contribution for(size_t sh = 0; sh < convShape.num_sh(); ++sh) { const number D_conv_flux = convShape(ip, sh); // Add flux term to local matrix J(_C_, scvf.from(), _C_, sh) += D_conv_flux; J(_C_, scvf.to(), _C_, sh) -= D_conv_flux; } }*/ } } // handle constrained dofs if(TFVGeom::usesHangingNodes){ for (size_t i=0;i<geo.num_constrained_dofs();i++){ const typename TFVGeom::CONSTRAINED_DOF& cd = geo.constrained_dof(i); const size_t index = cd.index(); J(_C_,index,_C_,index) = 1; for (size_t j=0;j<cd.num_constraining_dofs();j++) J(_C_, index, _C_, cd.constraining_dofs_index(j)) = -cd.constraining_dofs_weight(j); // insert interpolation equation directly for all dofs for (size_t j=0;j<geo.num_scv();j++){ const size_t nodeID = geo.scv(j).node_id(); number alpha=J(_C_,nodeID,_C_,index); J(_C_,nodeID,_C_,index)=0; for (size_t k=0;k<cd.num_constraining_dofs();k++) J(_C_,nodeID,_C_,cd.constraining_dofs_index(k)) += alpha*cd.constraining_dofs_weight(k); } } } /* UG_LOG("Local Matrix is: \n"); size_t n = geo.num_scv()+geo.num_constrained_dofs(); UG_LOG("locA=["); for (size_t i=0;i<n;i++){ for (size_t j=0;j<n;j++) UG_LOG(J(0,i,0,j) << " "); UG_LOG(";\n"); } UG_LOG("]\n");*/ //////////////////////////////////////////////////// // Reaction Term (using lumping) //////////////////////////////////////////////////// // if no data for reaction rate given, return if(!m_imReactionRate.data_given()) return; // loop Sub Control Volume (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) { // get current SCV const typename TFVGeom::SCV& scv = geo.scv(ip); // get associated node const int co = scv.node_id(); // Add to local matrix J(_C_, co, _C_, co) += m_imReactionRate[ip] * scv.volume(); } // reaction term does not explicitly depend on the associated unknown function }
int main() { clock_t start, stop; float lambda0 = 1.0, largeLambda, smallLambda; float tol = 0.00005, error = 10.0 * tol; float normSq, norm; int maxIter = 200, iter = 0, i; InitializeMatVec(); for (i = 0; i < rowMat * colMat; i++) { printf("i = %d \t A = %f \n", i, A[i]); // column-wise } // step 1: query platform info status = clGetPlatformIDs(0, NULL, &numPlatforms); platforms = (cl_platform_id*)malloc(numPlatforms *sizeof(cl_platform_id)); status = clGetPlatformIDs(numPlatforms, platforms, NULL); if (status != 0) { printf("Step 1: Failed to discover available platforms. Error code = %d. \n", status); } // step 2: query devices status = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_CPU, 0, NULL, &numDevices); devices = (cl_device_id*)malloc(numDevices *sizeof(cl_device_id)); status = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_CPU, numDevices, devices, NULL); if (status != 0) { printf("Step 2: Failed to discover available devices. Error code = %d. \n", status); } // step 3: create context for matrix-vector multiplication powerContext = clCreateContext(NULL, numDevices, devices, NULL, NULL, &powerStatus); if (powerStatus != 0) { printf("Step 3 kernel Power. Failed to create the context. Error code = %d. \n", powerStatus); } // step 3: create context for Jacobi iterative method iPowerContext = clCreateContext(NULL, numDevices, devices, NULL, NULL, &iPowerStatus); if (iPowerStatus != 0) { printf("Step 3 kernel iPower. Failed to create the context. Error code = %d. \n", iPowerStatus); } // step 4: set up command queue for matrix-vector multiplication powerQueue = clCreateCommandQueue(powerContext, devices[0], 0, &powerStatus); if (powerStatus != 0) { printf("Step 4 kernel Power. Failed to set up the command queue. Error code = %d. \n", powerStatus); } // step 4: set up command queue for Jacobi iterative method iPowerQueue = clCreateCommandQueue(iPowerContext, devices[0], 0, &iPowerStatus); if (iPowerStatus != 0) { printf("Step 4 kernel iPower. Failed to set up the command queue. Error code = %d. \n", iPowerStatus); } start = clock(); /* CALCULATE LARGEST EIGENVALUE */ MatVecMult(B); // obtain C, where C = A * B while (error > tol && iter < maxIter) { normSq = VecMult(C, C); norm = sqrt(normSq); for (i = 0; i < rowVec * colVec; i++) { Chat[i] = C[i] / norm; // normalize C } // obtain Rayleigh quotient tranpose(Chat) * A * Chat MatVecMult(Chat); // 1st part of Rayleigh. Also updates old C with new C. largeLambda = VecMult(Chat, C); // continue with 2nd part error = fabs((largeLambda - lambda0) / largeLambda); // relative error lambda0 = largeLambda; // update old eigenvalue with new one iter += 1; } // reset variables for next calculation lambda0 = 1.0, error = 10.0 * tol, maxIter = 200, iter = 0, normSq = 0.0, norm = 0.0; /* CALCULATE SMALLEST EIGENVALUE */ Jacobi(B, B); // Solve A * B = B. The solution is labeled X. while (error > tol && iter < maxIter) { normSq = VecMult(X, X); norm = sqrt(normSq); for (i = 0; i < rowVec * colVec; i++) { Xhat[i] = X[i] / norm; // normalize X } // obtain Rayleigh quotient tranpose(Xhat) * A * Xhat MatVecMult(Xhat); // 1st part of Rayleigh: C = transpose(Xhat) * A smallLambda = VecMult(C, Xhat); // 2nd part of Rayleigh error = fabs((smallLambda - lambda0) / smallLambda); // relative error lambda0 = smallLambda; // update old smallest eigenvalue with new one Jacobi(X, Xhat); // update old solution with new one iter += 1; } stop = clock(); printf("The largest eigenvalue is %f \n", largeLambda); printf("The smallest eigenvalue is %f \n", smallLambda); printf("The condition number of the matrix is %f \n", fabs(largeLambda / smallLambda)); printf("OpenCL CPU elapsed time = %f seconds. \n", (double)(stop - start) / CLOCKS_PER_SEC); // step 14: free used memory clReleaseKernel(powerKernel); clReleaseKernel(iPowerKernel); clReleaseProgram(powerProgram); clReleaseProgram(iPowerProgram); clReleaseCommandQueue(powerQueue); clReleaseCommandQueue(iPowerQueue); clReleaseMemObject(bufferA); clReleaseMemObject(bufferB); clReleaseMemObject(bufferC); clReleaseMemObject(bufferX); clReleaseContext(powerContext); clReleaseContext(iPowerContext); free(A); free(B); free(C); free(Chat); free(X); free(Xhat); free(platforms); free(devices); if (status != 0) { printf("Step 13: Failed to deallocate memory. Error code = %d. \n", status); } }
void DimCRFVGeometry<TDim, TWorldDim>:: update_boundary_faces(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish) { // get grid Grid& grid = *(ish->grid()); // vector of subset indices of side std::vector<int> vSubsetIndex; // get subset indices for sides (i.e. edge in 2d, faces in 3d) if(dim == 1) { std::vector<Vertex*> vVertex; CollectVertices(vVertex, grid, pElem); vSubsetIndex.resize(vVertex.size()); for(size_t i = 0; i < vVertex.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vVertex[i]); } if(dim == 2) { std::vector<Edge*> vEdges; CollectEdgesSorted(vEdges, grid, pElem); vSubsetIndex.resize(vEdges.size()); for(size_t i = 0; i < vEdges.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vEdges[i]); } if(dim == 3) { std::vector<Face*> vFaces; CollectFacesSorted(vFaces, grid, pElem); vSubsetIndex.resize(vFaces.size()); for(size_t i = 0; i < vFaces.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vFaces[i]); } try{ // const DimReferenceElement<dim>& rRefElem // = ReferenceElementProvider::get<dim>(m_roid); DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid); rMapping.update(vCornerCoords); const LocalShapeFunctionSet<dim>& TrialSpace = LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)); // loop requested subset typename std::map<int, std::vector<BF> >::iterator it; for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it) { // get subset index const int bndIndex = (*it).first; // get vector of BF for element std::vector<BF>& vBF = (*it).second; // clear vector vBF.clear(); // current number of bf size_t curr_bf = 0; // loop sides of element for(size_t side = 0; side < vSubsetIndex.size(); ++side) { // skip non boundary sides if(vSubsetIndex[side] != bndIndex) continue; // number of corners of side // const int coOfSide = rRefElem.num(dim-1, side, 0); todo use somewhere? // resize vector vBF.resize(curr_bf + 1); // fill BF with data from associated SCV BF& bf = vBF[curr_bf]; bf.nodeID = m_vSCV[side].nodeID; bf.localIP = m_vSCV[side].vLocIP; bf.globalIP = m_vSCV[side].vGlobIP; bf.Normal = m_vSCV[side].Normal; // compute volume bf.Vol = VecTwoNorm(bf.Normal); bf.numCo = m_vSCV[side].numCorners-1; // compute shapes and grads bf.numSH = TrialSpace.num_sh(); TrialSpace.shapes(&(bf.vShape[0]), bf.localIP); TrialSpace.grads(&(bf.vLocalGrad[0]), bf.localIP); // get reference mapping rMapping.jacobian_transposed_inverse(bf.JtInv, bf.localIP); bf.detj = rMapping.sqrt_gram_det(bf.localIP); // compute global gradients for(size_t sh = 0 ; sh < bf.num_sh(); ++sh) MatVecMult(bf.vGlobalGrad[sh], bf.JtInv, bf.vLocalGrad[sh]); // increase curr_bf ++curr_bf; } } } UG_CATCH_THROW("DimCRFVGeometry: update failed."); }
void DimCRFVGeometry<TDim, TWorldDim>:: update_hanging(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish,bool keepSCV,bool keepSCVF) { // If already update for this element, do nothing if(m_pElem == pElem) return; else m_pElem = pElem; // get grid Grid& grid = *(ish->grid()); // refresh local data, if different roid given if(m_roid != pElem->reference_object_id()) { // remember new roid m_roid = (ReferenceObjectID) pElem->reference_object_id(); // update local data update_local_data(); m_numDofs = num_scv(); } const LocalShapeFunctionSet<dim>& rTrialSpace = LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)); // compute barycenter coordinates globalBary = vCornerCoords[0]; for (size_t j=1;j<m_rRefElem.num(0);j++){ globalBary+=vCornerCoords[j]; } globalBary*=1./(number)m_rRefElem.num(0); // compute global informations for scvf for(size_t i = 0; i < num_scvf(); ++i) { for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){ m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)]; } m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary; AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo); ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type } // compute size of scv for(size_t i = 0; i < num_scv(); ++i) { // side nodes in reverse order to fulfill standard element order for (int j=0;j<m_vSCV[i].numCorners-1;j++){ m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)]; } AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1); m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i]; m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary; // compute volume of scv and normal to associated element face //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners); if (m_vSCV[i].numCorners-1==dim){ m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid) m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type1,worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); }; // nodes are in reverse order therefore reverse sign to get outward normal m_vSCV[i].Normal*=-1; } // get reference mapping DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid); rMapping.update(vCornerCoords); // check for hanging nodes if (dim==2){ std::vector<Edge*> vEdges; CollectEdgesSorted(vEdges, grid, pElem); for(size_t side = 0; side < vEdges.size(); ++side){ ConstrainingEdge* constrainingObj = dynamic_cast<ConstrainingEdge*>(vEdges[side]); if(constrainingObj == NULL) continue; // found constraining edge MathVector<worldDim> globalMidpoint = m_vSCV[side].vGlobIP; MathVector<dim> localMidpoint = m_vSCV[side].vLocIP; // get edge corners size_t edgeCo[2]; for (size_t j=0;j<2;j++) edgeCo[j] = m_rRefElem.id(1,side,0,j); // compute dof positions on constraining edge, // replace dof "side" with first and insert second at the end // set up new scvs // keepSCV parameter specifies if scv "side" gets replaced by new one size_t ind=side; size_t keepOffset=0; MathVector<worldDim> normal = m_vSCV[side].Normal; normal*=0.5; number vol = 0.5*m_vSCV[side].Vol; if (keepSCV){ ind=m_numSCV+1; keepOffset=1; } for (int d=0;d<worldDim;d++) m_vGlobUnkCoords[ind][d] = 0.5 * (vCornerCoords[edgeCo[0]][d] + globalMidpoint[d]); for (int d=0;d<dim;d++) m_vLocUnkCoords[ind][d] = 0.5 * (m_rRefElem.corner(edgeCo[0])[d] + localMidpoint[d]); for (int d=0;d<worldDim;d++) m_vGlobUnkCoords[m_numSCV][d] = 0.5 * (vCornerCoords[edgeCo[1]][d] + globalMidpoint[d]); for (int d=0;d<dim;d++) m_vLocUnkCoords[m_numSCV][d] = 0.5 * (m_rRefElem.corner(edgeCo[1])[d] + localMidpoint[d]); // handle corresponding scvfs // if keepSCVF copy them into constrained scvf array if (keepSCVF){ for (size_t j=0;j<2;j++){ m_vConstrainedSCVF[m_numConstrainedSCVF+j] = m_vSCVF[edgeCo[j]]; if (m_vConstrainedSCVF[edgeCo[j]].To==side){ m_vConstrainedSCVF[edgeCo[j]].From=side; m_vConstrainedSCVF[edgeCo[j]].Normal*=-1; } } m_numConstrainedSCVF += 2; } for (size_t j=0;j<2;j++){ if (m_vSCVF[edgeCo[j]].From==side) m_vSCVF[edgeCo[j]].From=m_numDofs+j; if (m_vSCVF[edgeCo[j]].To==side) m_vSCVF[edgeCo[j]].To=m_numDofs+j; } m_vSCV[ind].Normal = normal; m_vSCV[ind].Vol = vol; m_vSCV[ind].nodeID = m_numDofs; m_vSCV[ind].vGlobIP = m_vGlobUnkCoords[ind]; m_vSCV[ind].vLocIP = m_vLocUnkCoords[ind]; m_vSCV[ind].numSH = rTrialSpace.num_sh(); m_vSCV[ind].vGloPos[0]=vCornerCoords[edgeCo[0]]; m_vSCV[ind].vGloPos[1]=globalMidpoint; m_vSCV[ind].vGloPos[2]=globalBary; m_vSCV[ind].vLocPos[0]=m_rRefElem.corner(edgeCo[0]); m_vSCV[ind].vLocPos[1]=localMidpoint; m_vSCV[ind].vLocPos[2]=localBary; m_vSCV[ind].numCorners = 3; rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip()); rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip()); // second scv inserted at the end m_vSCV[m_numSCV].Normal = normal; m_vSCV[m_numSCV].Vol = vol; m_vSCV[m_numSCV].nodeID = m_numDofs+1; m_vSCV[m_numSCV].vGlobIP = m_vGlobUnkCoords[m_numSCV]; m_vSCV[m_numSCV].vLocIP = m_vLocUnkCoords[m_numSCV]; m_vSCV[m_numSCV].numSH = rTrialSpace.num_sh(); m_vSCV[m_numSCV].vGloPos[0]=vCornerCoords[edgeCo[1]]; m_vSCV[m_numSCV].vGloPos[1]=globalMidpoint; m_vSCV[m_numSCV].vGloPos[2]=globalBary; m_vSCV[m_numSCV].vLocPos[0]=m_rRefElem.corner(edgeCo[1]); m_vSCV[m_numSCV].vLocPos[1]=localMidpoint; m_vSCV[m_numSCV].vLocPos[2]=localBary; m_vSCV[m_numSCV].numCorners = 3; rTrialSpace.shapes(&(m_vSCV[m_numSCV].vShape[0]), m_vSCV[m_numSCV].local_ip()); rTrialSpace.grads(&(m_vSCV[m_numSCV].vLocalGrad[0]), m_vSCV[m_numSCV].local_ip()); // insert new scvf m_vSCVF[m_numSCVF].From = m_numDofs; m_vSCVF[m_numSCVF].To = m_numDofs+1; m_vSCVF[m_numSCVF].vLocPos[0] = localMidpoint; m_vSCVF[m_numSCVF].vLocPos[1] = localBary; m_vSCVF[m_numSCVF].vGloPos[0] = globalMidpoint; m_vSCVF[m_numSCVF].vGloPos[1] = globalBary; m_vSCVF[m_numSCVF].numSH = rTrialSpace.num_sh(); for (int d=0;d<dim;d++) m_vSCVF[m_numSCVF].localIP[d] = 0.5*(localMidpoint[d] + localBary[d]); for (int d=0;d<worldDim;d++) m_vSCVF[m_numSCVF].globalIP[d] = 0.5*(globalMidpoint[d] + globalBary[d]); rTrialSpace.shapes(&(m_vSCVF[m_numSCVF].vShape[0]), m_vSCVF[m_numSCVF].local_ip()); rTrialSpace.grads(&(m_vSCVF[m_numSCVF].vLocalGrad[0]), m_vSCVF[m_numSCVF].local_ip()); ElementNormal<face_type0,worldDim>(m_vSCVF[m_numSCVF].Normal,m_vSCVF[m_numSCVF].vGloPos); // insert new constrained dof object m_vCD[m_numConstrainedDofs].i = side; m_vCD[m_numConstrainedDofs].numConstrainingDofs = 2; m_vCD[m_numConstrainedDofs].cDofInd[0] = m_numDofs; m_vCD[m_numConstrainedDofs].cDofInd[1] = m_numDofs+1; m_vCD[m_numConstrainedDofs].cDofWeights[0] = 0.5; m_vCD[m_numConstrainedDofs].cDofWeights[1] = 0.5; m_numSCV+=1+keepOffset; m_numSCVF+=1; m_numDofs+=2; m_numConstrainedDofs+=1; m_roid = ROID_UNKNOWN; } } else { // dim == 3 std::vector<Face*> vFaces; CollectFacesSorted(vFaces, grid, pElem); handledEdges.clear(); for(size_t face = 0; face < vFaces.size(); ++face){ ConstrainingFace* constrainingObj = dynamic_cast<ConstrainingFace*>(vFaces[face]); if(constrainingObj == NULL) continue; // found constraining face MathVector<worldDim> globalMidpoint = m_vSCV[face].vGlobIP; MathVector<dim> localMidpoint = m_vSCV[face].vLocIP; number faceVol = m_vSCV[face].Vol; MathVector<worldDim> faceNormal = m_vSCV[face].Normal; // get face corners and edges size_t faceCo[4]; size_t faceEdge[4]; // number of corners of face = number of edges size_t numFaceCo = m_rRefElem.num(2,face,0); for (size_t j=0;j<numFaceCo;j++) faceCo[j] = m_rRefElem.id(2,face,0,j); for (size_t j=0;j<numFaceCo;j++) faceEdge[j] = m_rRefElem.id(2,face,1,j); number volSum=0; size_t keepOffset=0; if (keepSCV) keepOffset=1; // compute coordinates of each face and fill scv values for (size_t i=0;i<numFaceCo;i++){ size_t co = faceCo[i]; size_t nOfEdges=0; size_t nbEdges[2]; // find 2 edges in face belonging to node for (size_t j=0;j<m_rRefElem.num(0,co,1);j++){ size_t candidate = m_rRefElem.id(0,co,1,j); bool found = false; for (size_t k=0;k<numFaceCo;k++){ if (faceEdge[k]==candidate){ found = true; break; } } if (found==true){ nbEdges[nOfEdges] = candidate; nOfEdges++; if (nOfEdges==2) break; } } // in triangular case switch edges if necessary for correct orientation if (numFaceCo==3){ if (faceEdge[i]==nbEdges[1]){ nbEdges[1] = nbEdges[0]; nbEdges[0] = faceEdge[i]; } } // keepSCV parameter specifies if scv "side" gets replaced by new one size_t ind = m_numSCV+i-1+keepOffset; if (i==0){ if (keepSCV) ind=m_numSCV; else ind = face; } // others are inserted at the end m_vSCV[ind].vGloPos[0] = vCornerCoords[co]; m_vSCV[ind].vLocPos[0] = m_rRefElem.corner(co); for (int d=0;d<worldDim;d++){ // edge 0 midpoint m_vSCV[ind].vGloPos[1][d] = 0.5 * ( vCornerCoords[m_rRefElem.id(1,nbEdges[0],0,0)][d] + vCornerCoords[m_rRefElem.id(1,nbEdges[0],0,1)][d] ); m_vSCV[ind].vLocPos[1][d] = 0.5 * ( m_rRefElem.corner(m_rRefElem.id(1,nbEdges[0],0,0))[d] + m_rRefElem.corner(m_rRefElem.id(1,nbEdges[0],0,1))[d] ); // edge 1 midpoint m_vSCV[ind].vGloPos[numFaceCo-1][d] = 0.5 * ( vCornerCoords[m_rRefElem.id(1,nbEdges[1],0,0)][d] + vCornerCoords[m_rRefElem.id(1,nbEdges[1],0,1)][d] ); m_vSCV[ind].vLocPos[numFaceCo-1][d] = 0.5 * ( m_rRefElem.corner(m_rRefElem.id(1,nbEdges[1],0,0))[d] + m_rRefElem.corner(m_rRefElem.id(1,nbEdges[1],0,1))[d] ); } if (numFaceCo==4) m_vSCV[ind].vGloPos[2] = globalMidpoint; m_vSCV[ind].vGloPos[numFaceCo] = globalBary; m_vSCV[ind].vLocPos[numFaceCo] = localBary; m_vSCV[ind].numCorners = numFaceCo + 1; AveragePositions(m_vGlobUnkCoords[ind], m_vSCV[ind].vGloPos, m_vSCV[ind].numCorners-1); AveragePositions(m_vLocUnkCoords[ind], m_vSCV[ind].vLocPos, m_vSCV[ind].numCorners-1); m_vSCV[ind].vLocIP = m_vLocUnkCoords[ind]; m_vSCV[ind].vGlobIP = m_vGlobUnkCoords[ind]; m_vSCV[ind].numSH = rTrialSpace.num_sh(); if (numFaceCo==3) m_vSCV[ind].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[ind].vGloPos); else m_vSCV[ind].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[ind].vGloPos); if (m_vSCV[ind].Vol<0) m_vSCV[ind].Vol *= -1; volSum+=m_vSCV[ind].Vol; m_vSCV[ind].Normal = faceNormal; m_vSCV[ind].Normal *= (number) m_vSCV[ind].Vol / faceVol; rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip()); rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip()); m_vSCV[ind].nodeID = m_numDofs+i; } // compute inner scv in triangular case if (numFaceCo==3){ size_t ind = m_numSCV+2+keepOffset; m_vSCV[ind].Vol = faceVol - volSum; m_vSCV[ind].nodeID=m_numDofs+3; m_vSCV[ind].Normal = faceNormal; m_vSCV[ind].Normal *= (number) m_vSCV[ind].Vol / faceVol; m_vSCV[ind].vGlobIP = m_vSCV[face].vGloPos[1]; m_vSCV[ind].vLocIP = m_vSCV[face].vLocPos[1]; for (size_t j=0;j<2;j++){ m_vSCV[ind].vGlobIP += m_vSCV[m_numSCV+j].vGloPos[1]; m_vSCV[ind].vLocIP += m_vSCV[m_numSCV+j].vLocPos[1]; } m_vSCV[ind].vGlobIP *= (number)1.0/3.0; m_vSCV[ind].vLocIP *= (number)1.0/3.0; m_vGlobUnkCoords[ind] = m_vSCV[ind].vGlobIP; m_vLocUnkCoords[ind] = m_vSCV[ind].vLocIP; m_vSCV[ind].numCorners = numFaceCo + 1; m_vSCV[ind].numSH = rTrialSpace.num_sh(); rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip()); rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip()); } // copy scvfs into constrained scvfs if (keepSCVF){ for (size_t i=0;i<numFaceCo;i++){ size_t edge = faceEdge[i]; m_vConstrainedSCVF[m_numConstrainedSCVF+i] = m_vSCVF[edge]; if (m_vConstrainedSCVF[m_numConstrainedSCVF+i].To==face){ m_vConstrainedSCVF[m_numConstrainedSCVF+i].From=face; m_vConstrainedSCVF[m_numConstrainedSCVF+i].Normal*=-1; } } m_numConstrainedSCVF += numFaceCo; } // insert new scvfs, first the ones associated to edges of face for (size_t i=0;i<numFaceCo;i++){ size_t edge = faceEdge[i]; size_t from = m_vSCVF[edge].From; size_t to = m_vSCVF[edge].To; MathVector<worldDim> normal = m_vSCVF[edge].Normal; normal*=0.5; size_t edgeCo[2]; size_t scvID[2]; for (size_t j=0;j<2;j++){ edgeCo[j] = m_rRefElem.id(1,edge,0,j); // find corresponding face vertex (= corresponding scv index) for (size_t k=0;k<numFaceCo;k++){ if (faceCo[k]==edgeCo[j]){ scvID[j] = m_numDofs+k; break; } } } // look if edge has already been handled if (m_numConstrainedDofs>0){ bool found=false; for (size_t j=0;j<handledEdges.size();j++){ if (handledEdges[j].index==edge){ HandledEdge& hE=handledEdges[j]; found=true; // set new from/to values for (size_t k=0;k<2;k++){ if (hE.from){ m_vSCVF[hE.scvfIndex+k].To=scvID[k]; } else { m_vSCVF[hE.scvfIndex+k].From=scvID[k]; } } // mark edge so associated scvf is not overwritten faceEdge[i]=deleted; break; } } if (found==true) continue; } HandledEdge hEdge; hEdge.index=edge; hEdge.scvfIndex=m_numSCVF; MathVector<worldDim> edgeMidGlob; MathVector<dim> edgeMidLoc; for (int d=0;d<worldDim;d++){ edgeMidGlob[d] = 0.5 * (vCornerCoords[edgeCo[0]][d] + vCornerCoords[edgeCo[1]][d]); edgeMidLoc[d] = 0.5 * (m_rRefElem.corner(edgeCo[0])[d] + m_rRefElem.corner(edgeCo[1])[d]); } for (size_t j=0;j<2;j++){ hEdge.associatedSCV[j] = scvID[j]; if (from==face){ m_vSCVF[m_numSCVF].From = scvID[j]; m_vSCVF[m_numSCVF].To = to; hEdge.from=true; } else { m_vSCVF[m_numSCVF].From = from; m_vSCVF[m_numSCVF].To = scvID[j]; hEdge.from=false; } m_vSCVF[m_numSCVF].Normal = normal; m_vSCVF[m_numSCVF].vGloPos[0] = vCornerCoords[edgeCo[j]]; m_vSCVF[m_numSCVF].vLocPos[0] = m_rRefElem.corner(edgeCo[j]); m_vSCVF[m_numSCVF].vGloPos[1] = edgeMidGlob; m_vSCVF[m_numSCVF].vLocPos[1] = edgeMidLoc; m_vSCVF[m_numSCVF].vGloPos[2] = globalBary; m_vSCVF[m_numSCVF].vLocPos[2] = localBary; m_vSCVF[m_numSCVF].numSH = rTrialSpace.num_sh(); AveragePositions(m_vSCVF[m_numSCVF].localIP, m_vSCVF[m_numSCVF].vLocPos, m_vSCVF[m_numSCVF].numCo); AveragePositions(m_vSCVF[m_numSCVF].globalIP, m_vSCVF[m_numSCVF].vGloPos, m_vSCVF[m_numSCVF].numCo); rTrialSpace.shapes(&(m_vSCVF[m_numSCVF].vShape[0]), m_vSCVF[m_numSCVF].local_ip()); rTrialSpace.grads(&(m_vSCVF[m_numSCVF].vLocalGrad[0]), m_vSCVF[m_numSCVF].local_ip()); m_numSCVF++; } handledEdges.push_back(hEdge); } // scvfs inside the face // insert remaining inner scvfs into positions of edge associated scvs for (size_t j=0;j<numFaceCo;j++){ // replaces edge associated scvf size_t ii = faceEdge[j]; if (ii==deleted){ ii = m_numSCVF; m_numSCVF++; } if (numFaceCo==3){ // compute inner scvfs in triangular case m_vSCVF[ii].From = m_numDofs+3; m_vSCVF[ii].To = m_numDofs+j; size_t ind = face; if (j>0) ind = m_numSCV+j-1; m_vSCVF[ii].vLocPos[0] = m_vSCV[ind].vLocPos[1]; m_vSCVF[ii].vLocPos[1] = m_vSCV[ind].vLocPos[2]; m_vSCVF[ii].vGloPos[0] = m_vSCV[ind].vGloPos[1]; m_vSCVF[ii].vGloPos[1] = m_vSCV[ind].vGloPos[2]; }else{ // compute inner scvfs in quadrilateral case m_vSCVF[ii].To = m_numDofs+j; m_vSCVF[ii].From = m_numDofs + ((j+1) % 4); for (int d=0;d<worldDim;d++){ m_vSCVF[ii].vLocPos[0][d] = 0.5*( m_rRefElem.corner(faceCo[j])[d] + m_rRefElem.corner(faceCo[(j+1) % 4])[d] ); m_vSCVF[ii].vGloPos[0][d] = 0.5*( vCornerCoords[faceCo[j]][d] + vCornerCoords[faceCo[(j+1) % 4]][d] ); } m_vSCVF[ii].vLocPos[1] = localMidpoint; m_vSCVF[ii].vGloPos[1] = globalMidpoint; } m_vSCVF[ii].vLocPos[2] = localBary; m_vSCVF[ii].vGloPos[2] = globalBary; m_vSCVF[ii].numSH = rTrialSpace.num_sh(); ElementNormal<face_type0,worldDim>(m_vSCVF[ii].Normal,m_vSCVF[ii].vGloPos); AveragePositions(m_vSCVF[ii].globalIP,m_vSCVF[ii].vGloPos,3); AveragePositions(m_vSCVF[ii].localIP,m_vSCVF[ii].vLocPos,3); rTrialSpace.shapes(&(m_vSCVF[ii].vShape[0]), m_vSCVF[ii].local_ip()); rTrialSpace.grads(&(m_vSCVF[ii].vLocalGrad[0]), m_vSCVF[ii].local_ip()); } // insert new constrained dof object m_vCD[m_numConstrainedDofs].i = face; m_vCD[m_numConstrainedDofs].numConstrainingDofs = 4; for (size_t i=0;i<4;i++){ m_vCD[m_numConstrainedDofs].cDofInd[i] = m_numDofs+i; size_t ind=face; if (i>0) ind = m_numSCV+i-1; m_vCD[m_numConstrainedDofs].cDofWeights[i] = (number)m_vSCV[ind].Vol / faceVol; } m_numSCV+=3+keepOffset; m_numDofs+=4; m_numConstrainedDofs+=1; m_roid = ROID_UNKNOWN; } }// end of hanging node check //\todo compute with one virt. call // compute jacobian for linear mapping if(rMapping.is_linear()) { MathMatrix<worldDim,dim> JtInv; rMapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip()); const number detJ = rMapping.sqrt_gram_det(m_vSCVF[0].local_ip()); for(size_t i = 0; i < num_scvf(); ++i) { m_vSCVF[i].JtInv = JtInv; m_vSCVF[i].detj = detJ; } for(size_t i = 0; i < num_scv(); ++i) { m_vSCV[i].JtInv = JtInv; m_vSCV[i].detj = detJ; } } // else compute jacobian for each integration point else { for(size_t i = 0; i < num_scvf(); ++i) { rMapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip()); m_vSCVF[i].detj = rMapping.sqrt_gram_det(m_vSCVF[i].local_ip()); } for(size_t i = 0; i < num_scv(); ++i) { rMapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip()); m_vSCV[i].detj = rMapping.sqrt_gram_det(m_vSCV[i].local_ip()); } } // compute global gradients for(size_t i = 0; i < num_scvf(); ++i) for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh) MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]); for(size_t i = 0; i < num_scv(); ++i) for(size_t sh = 0; sh < scv(i).num_sh(); ++sh) MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]); // copy ip points in list (SCVF) for(size_t i = 0; i < num_scvf(); ++i) m_vGlobSCVF_IP[i] = scvf(i).global_ip(); // if no boundary subsets required, return if(num_boundary_subsets() == 0 || ish == NULL) return; else update_boundary_faces(pElem, vCornerCoords, ish); }
void DimCRFVGeometry<TDim, TWorldDim>:: update(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish) { // If already update for this element, do nothing if(m_pElem == pElem) return; else m_pElem = pElem; // refresh local data, if different roid given if(m_roid != pElem->reference_object_id()) { // remember new roid m_roid = (ReferenceObjectID) pElem->reference_object_id(); // update local data update_local_data(); } // get reference element try{ const DimReferenceElement<dim>& m_rRefElem = ReferenceElementProvider::get<dim>(m_roid); // compute barycenter coordinates globalBary = vCornerCoords[0]; for (size_t j=1;j<m_rRefElem.num(0);j++){ globalBary+=vCornerCoords[j]; } globalBary*=1./(number)m_rRefElem.num(0); // compute global informations for scvf for(size_t i = 0; i < num_scvf(); ++i) { for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){ m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)]; } m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary; AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo); ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type } // compute size of scv for(size_t i = 0; i < num_scv(); ++i) { // side nodes in reverse order to fulfill standard element order for (int j=0;j<m_vSCV[i].numCorners-1;j++){ m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)]; } AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1); m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i]; m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary; // compute volume of scv and normal to associated element face //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners); if (m_vSCV[i].numCorners-1==dim){ m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid) m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type1,worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); }; // nodes are in reverse order therefore reverse sign to get outward normal m_vSCV[i].Normal*=-1; } // get reference mapping DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid); rMapping.update(vCornerCoords); //\todo compute with on virt. call // compute jacobian for linear mapping if(rMapping.is_linear()) { MathMatrix<worldDim,dim> JtInv; rMapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip()); const number detJ = rMapping.sqrt_gram_det(m_vSCVF[0].local_ip()); for(size_t i = 0; i < num_scvf(); ++i) { m_vSCVF[i].JtInv = JtInv; m_vSCVF[i].detj = detJ; } for(size_t i = 0; i < num_scv(); ++i) { m_vSCV[i].JtInv = JtInv; m_vSCV[i].detj = detJ; } } // else compute jacobian for each integration point else { for(size_t i = 0; i < num_scvf(); ++i) { rMapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip()); m_vSCVF[i].detj = rMapping.sqrt_gram_det(m_vSCVF[i].local_ip()); } for(size_t i = 0; i < num_scv(); ++i) { rMapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip()); m_vSCV[i].detj = rMapping.sqrt_gram_det(m_vSCV[i].local_ip()); } } // compute global gradients for(size_t i = 0; i < num_scvf(); ++i) for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh) MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]); for(size_t i = 0; i < num_scv(); ++i) for(size_t sh = 0; sh < scv(i).num_sh(); ++sh) MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]); // copy ip points in list (SCVF) for(size_t i = 0; i < num_scvf(); ++i) m_vGlobSCVF_IP[i] = scvf(i).global_ip(); } UG_CATCH_THROW("DimCRFVGeometry: update failed."); // if no boundary subsets required, return if(num_boundary_subsets() == 0 || ish == NULL) return; else update_boundary_faces(pElem, vCornerCoords, ish); }
void CRFVGeometry<TElem, TWorldDim>:: update_boundary_faces(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish) { // get grid Grid& grid = *(ish->grid()); // vector of subset indices of side std::vector<int> vSubsetIndex; // get subset indices for sides (i.e. edge in 2d, faces in 3d) if(dim == 1) { std::vector<Vertex*> vVertex; CollectVertices(vVertex, grid, pElem); vSubsetIndex.resize(vVertex.size()); for(size_t i = 0; i < vVertex.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vVertex[i]); } if(dim == 2) { std::vector<Edge*> vEdges; CollectEdgesSorted(vEdges, grid, pElem); vSubsetIndex.resize(vEdges.size()); for(size_t i = 0; i < vEdges.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vEdges[i]); } if(dim == 3) { std::vector<Face*> vFaces; CollectFacesSorted(vFaces, grid, pElem); vSubsetIndex.resize(vFaces.size()); for(size_t i = 0; i < vFaces.size(); ++i) vSubsetIndex[i] = ish->get_subset_index(vFaces[i]); } // loop requested subset typename std::map<int, std::vector<BF> >::iterator it; for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it) { // get subset index const int bndIndex = (*it).first; // get vector of BF for element std::vector<BF>& vBF = (*it).second; // clear vector vBF.clear(); // current number of bf size_t curr_bf = 0; // loop sides of element for(size_t side = 0; side < vSubsetIndex.size(); ++side) { // skip non boundary sides if(vSubsetIndex[side] != bndIndex) continue; // resize vector vBF.resize(curr_bf + 1); // fill BF with data from associated SCV BF& bf = vBF[curr_bf]; bf.nodeID = m_vSCV[side].nodeID; bf.localIP = m_vSCV[side].vLocIP; bf.globalIP = m_vSCV[side].vGlobIP; bf.Normal = m_vSCV[side].Normal; // compute volume bf.Vol = VecTwoNorm(bf.Normal); bf.numCo = m_vSCV[side].numCorners-1; // compute shapes and grads m_rTrialSpace.shapes(&(bf.vShape[0]), bf.localIP); m_rTrialSpace.grads(&(bf.vLocalGrad[0]), bf.localIP); // get reference mapping m_mapping.jacobian_transposed_inverse(bf.JtInv, bf.localIP); bf.detj = m_mapping.sqrt_gram_det(bf.localIP); // compute global gradients for(size_t sh = 0 ; sh < bf.num_sh(); ++sh) MatVecMult(bf.vGlobalGrad[sh], bf.JtInv, bf.vLocalGrad[sh]); // increase curr_bf ++curr_bf; } } }
void CRFVGeometry<TElem, TWorldDim>:: update(GridObject* elem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish) { UG_ASSERT(dynamic_cast<TElem*>(elem) != NULL, "Wrong element type."); TElem* pElem = static_cast<TElem*>(elem); // If already update for this element, do nothing if(m_pElem == pElem) return; else m_pElem = pElem; // compute barycenter coordinates globalBary = vCornerCoords[0]; m_vCo[0] = vCornerCoords[0]; for (size_t j=1;j<m_rRefElem.num(0);j++){ globalBary+=vCornerCoords[j]; m_vCo[j] = vCornerCoords[j]; } globalBary*=1./(number)m_rRefElem.num(0); // compute global informations for scvf for(size_t i = 0; i < num_scvf(); ++i) { for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){ m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)]; } m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary; AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo); ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type } // compute size of scv for(size_t i = 0; i < num_scv(); ++i) { // side nodes in reverse order to fulfill standard element order for (int j=0;j<m_vSCV[i].numCorners-1;j++){ m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)]; } AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1); m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i]; m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary; // compute volume of scv and normal to associated element face //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners); if (m_vSCV[i].numCorners-1==dim){ m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid) m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos); ElementNormal<face_type1, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos); }; // nodes are in reverse order therefore reverse sign to get outward normal m_vSCV[i].Normal*=-1; } // Shapes and Derivatives m_mapping.update(vCornerCoords); // compute jacobian for linear mapping if(ReferenceMapping<ref_elem_type, worldDim>::isLinear) { MathMatrix<worldDim,dim> JtInv; m_mapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip()); const number detJ = m_mapping.sqrt_gram_det(m_vSCVF[0].local_ip()); for(size_t i = 0; i < num_scvf(); ++i) { m_vSCVF[i].JtInv = JtInv; m_vSCVF[i].detj = detJ; } for(size_t i = 0; i < num_scv(); ++i) { m_vSCV[i].JtInv = JtInv; m_vSCV[i].detj = detJ; } } // else compute jacobian for each integration point else { for(size_t i = 0; i < num_scvf(); ++i) { m_mapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip()); m_vSCVF[i].detj = m_mapping.sqrt_gram_det(m_vSCVF[i].local_ip()); } for(size_t i = 0; i < num_scv(); ++i) { m_mapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip()); m_vSCV[i].detj = m_mapping.sqrt_gram_det(m_vSCV[i].local_ip()); } } // compute global gradients for(size_t i = 0; i < num_scvf(); ++i) for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh) MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]); for(size_t i = 0; i < num_scv(); ++i) for(size_t sh = 0; sh < scv(i).num_sh(); ++sh) MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]); // copy ip points in list (SCVF) for(size_t i = 0; i < num_scvf(); ++i) m_vGlobSCVF_IP[i] = scvf(i).global_ip(); // if no boundary subsets required, return if(num_boundary_subsets() == 0 || ish == NULL) return; else update_boundary_faces(pElem, vCornerCoords, ish); }
void ConvectionDiffusionFE<TDomain>:: ex_grad(MathVector<dim> vValue[], const MathVector<dim> vGlobIP[], number time, int si, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const MathVector<TFEGeom::dim> vLocIP[], const size_t nip, bool bDeriv, std::vector<std::vector<MathVector<dim> > > vvvDeriv[]) { // request geometry const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder); // reference element typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type; // reference dimension static const int refDim = reference_element_traits<TElem>::dim; // reference object id static const ReferenceObjectID roid = ref_elem_type::REFERENCE_OBJECT_ID; // FE if(vLocIP == geo.local_ips()) { // Loop ip for(size_t ip = 0; ip < geo.num_ip(); ++ip) { VecSet(vValue[ip], 0.0); for(size_t sh = 0; sh < geo.num_sh(); ++sh) VecScaleAppend(vValue[ip], u(_C_, sh), geo.global_grad(ip, sh)); if(bDeriv) for(size_t sh = 0; sh < geo.num_sh(); ++sh) vvvDeriv[ip][_C_][sh] = geo.global_grad(ip, sh); } } // general case else { // request for trial space try{ const LocalShapeFunctionSet<refDim>& rTrialSpace = LocalFiniteElementProvider::get<refDim>(roid, m_lfeID); // number of shape functions const size_t numSH = rTrialSpace.num_sh(); // storage for shape function at ip std::vector<MathVector<refDim> > vLocGrad(numSH); MathVector<refDim> locGrad; // Reference Mapping MathMatrix<dim, refDim> JTInv; ReferenceMapping<ref_elem_type, dim> mapping(vCornerCoords); // loop ips for(size_t ip = 0; ip < nip; ++ip) { // evaluate at shapes at ip rTrialSpace.grads(vLocGrad, vLocIP[ip]); // compute grad at ip VecSet(locGrad, 0.0); for(size_t sh = 0; sh < numSH; ++sh) VecScaleAppend(locGrad, u(_C_, sh), vLocGrad[sh]); // compute global grad mapping.jacobian_transposed_inverse(JTInv, vLocIP[ip]); MatVecMult(vValue[ip], JTInv, locGrad); // compute derivative w.r.t. to unknowns iff needed if(bDeriv) for(size_t sh = 0; sh < numSH; ++sh) MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]); } } UG_CATCH_THROW("ConvectionDiffusion::ex_grad: trial space missing."); } };
void GradientDataExport<dim>::eval_and_deriv(MathVector<dim> vValue[], const MathVector<dim> vGlobIP[], number time, int si, GridObject* elem, const MathVector<dim> vCornerCoords[], const MathVector<refDim> vLocIP[], const size_t nip, LocalVector* u, bool bDeriv, int s, std::vector<std::vector<MathVector<dim> > > vvvDeriv[], const MathMatrix<refDim, dim>* vJT) const { // abbreviation for component static const int _C_ = 0; // reference object id const ReferenceObjectID roid = elem->reference_object_id(); // local finite element id const LFEID& lfeID = this->function_group().local_finite_element_id(_C_); // access local vector by map u->access_by_map(this->map()); // request for trial space try{ const LocalShapeFunctionSet<refDim>& rTrialSpace = LocalFiniteElementProvider::get<refDim>(roid, lfeID); // Reference Mapping MathMatrix<dim, refDim> JTInv; std::vector<MathMatrix<refDim, dim> > vJTtmp; if(!vJT){ DimReferenceMapping<refDim, dim>& map = ReferenceMappingProvider::get<refDim, dim>(roid, vCornerCoords); vJTtmp.resize(nip); map.jacobian_transposed(&vJTtmp[0], vLocIP, nip); vJT = &vJTtmp[0]; } // storage for shape function at ip std::vector<MathVector<refDim> > vLocGrad; MathVector<refDim> locGrad; // loop ips for(size_t ip = 0; ip < nip; ++ip) { // evaluate at shapes at ip rTrialSpace.grads(vLocGrad, vLocIP[ip]); // compute grad at ip VecSet(locGrad, 0.0); for(size_t sh = 0; sh < vLocGrad.size(); ++sh) VecScaleAppend(locGrad, (*u)(_C_, sh), vLocGrad[sh]); Inverse(JTInv, vJT[ip]); MatVecMult(vValue[ip], JTInv, locGrad); // store derivative if(bDeriv) for(size_t sh = 0; sh < vLocGrad.size(); ++sh) MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]); } } UG_CATCH_THROW("GradientDataExport: Trial space missing, Reference Object: " <<roid<<", Trial Space: "<<lfeID<<", refDim="<<refDim); }