Ejemplo n.º 1
0
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;
			}
		}
	}
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 9
0
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);
	}
}
Ejemplo n.º 10
0
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.");
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
0
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;
		}
	}
}
Ejemplo n.º 14
0
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.");
	}
};
Ejemplo n.º 16
0
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);
}