//$EK 2013-03-05 added
void IntegrationRule::DefineIntegrationRulePrism(IntegrationRule & integrationRule, int ruleOrder)
{
	// we use a ready function, which provides a tetrahedral integration rule
	Vector x1, x2, xline, w, wline;
	GetIntegrationRuleTrig(x1, x2, w, ruleOrder);
	GetIntegrationRule(xline, wline, ruleOrder);
	for (int i = 1; i <= xline.Length(); ++i)
		xline(i) = (xline(i) + 1.)/2.;
	
	// and now we create a 3D integration rule
	integrationRule.integrationPoints.SetLen(x1.Length()*xline.Length());
	assert(x1.Length() == x2.Length());
	assert(x1.Length() == w.Length());
	assert(xline.Length() == wline.Length());
	int cnt = 1;
	for (int i1 = 1; i1 <= x1.GetLen(); i1++)
	{
		for (int i2 = 1; i2 <= xline.GetLen(); ++i2)
		{
			integrationRule.integrationPoints(cnt).x = x1(i1);
			integrationRule.integrationPoints(cnt).y = x2(i1);
			integrationRule.integrationPoints(cnt).z = xline(i2);
			//the /2. is due to the transformation of [-1,1] to [0,1]
			integrationRule.integrationPoints(cnt).weight = w(i1)*wline(i2)/2.;
			cnt++;
	  }
	}
}
void IntegrationRule::DefineIntegrationRuleCube(IntegrationRule & integrationRule, int ruleOrder)
{
	// we use a ready function, which provides a one-dimensional integration rule
	Vector x;
	Vector w;
	GetIntegrationRule(x ,w, ruleOrder);

	// and now we create a 3D integration rule
	integrationRule.integrationPoints.SetLen(x.Length() * x.Length() * x.Length());
	int cnt = 1;
	for (int i1 = 1; i1 <= x.GetLen(); i1++)
	{
		for (int i2 = 1; i2 <= x.GetLen(); i2++)
		{
			for (int i3 = 1; i3 <= x.GetLen(); i3++)
			{
				integrationRule.integrationPoints(cnt).x = x(i1);
				integrationRule.integrationPoints(cnt).y = x(i2);
				integrationRule.integrationPoints(cnt).z = x(i3);
				integrationRule.integrationPoints(cnt).weight = w(i1) * w(i2) * w(i3);
				cnt++;
			}
		}
	}
}
void IntegrationRule::DefineIntegrationRuleLine(IntegrationRule & integrationRule, int ruleOrder)
{
	// we use a ready function, which provides a one-dimensional integration rule
	Vector x, w;
	GetIntegrationRule(x, w, ruleOrder);

	integrationRule.integrationPoints.SetLen(x.Length());
	for (int i = 1; i <= x.GetLen(); i++)
	{
		integrationRule.integrationPoints(i).x = x(i);
		integrationRule.integrationPoints(i).y = 0.;
		integrationRule.integrationPoints(i).z = 0.;
		integrationRule.integrationPoints(i).weight = w(i);
	}
}
void IntegrationRule::DefineIntegrationRuleTriangle(IntegrationRule & integrationRule, int ruleOrder)
{
	// we use a ready function, which provides a triangular integration rule
	Vector x1, x2, w;
	GetIntegrationRuleTrig(x1, x2, w, ruleOrder);

	// and now we create a 3D integration rule
	integrationRule.integrationPoints.SetLen(x1.Length());
	assert(x1.Length() == x2.Length());
	assert(x1.Length() == w.Length());
	for (int i1 = 1; i1 <= x1.GetLen(); i1++)
	{
		integrationRule.integrationPoints(i1).x = x1(i1);
		integrationRule.integrationPoints(i1).y = x2(i1);
		integrationRule.integrationPoints(i1).z = 0;
		integrationRule.integrationPoints(i1).weight = w(i1);
	}
}
//$EK 2013-03-05 added
void IntegrationRule::DefineIntegrationRulePyramid(IntegrationRule & integrationRule, int ruleOrder)
{
	// we use a ready function, which provides a tetrahedral integration rule
	Vector x_z, xline, w_z, wline;
	//$EK I don't know why in z-direction one needs in increased order???
	//-------------------------------------------------------------------------
	//FROM NGSolve ... prismatic integration rule (in intrule.cpp)
	//		const IntegrationRule & quadrule = SelectIntegrationRule (ET_QUAD, order);
	//	const IntegrationRule & segrule = SelectIntegrationRule (ET_SEGM, order+2);
	//const IntegrationPoint & ipquad = quadrule[i]; // .GetIP(i);
	//const IntegrationPoint & ipseg = segrule[j]; // .GetIP(j);
	//point[0] = (1-ipseg(0)) * ipquad(0);
	//point[1] = (1-ipseg(0)) * ipquad(1);
	//point[2] = ipseg(0);
	//weight = ipseg.Weight() * sqr (1-ipseg(0)) * ipquad.Weight();
	//--------------------------------------------------------------------------
	GetIntegrationRule(x_z, w_z, ruleOrder+2);
	GetIntegrationRule(xline, wline, ruleOrder);
	//adapt integration points to interval [0,1] instead of [-1,1]
	for (int i = 1; i <= xline.Length(); ++i)
		xline(i) = (xline(i) + 1.)/2.;
	for (int i = 1; i <= x_z.Length(); ++i)
		x_z(i) = (x_z(i) + 1.)/2.;
	
	// and now we create a 3D integration rule
	integrationRule.integrationPoints.SetLen(x_z.Length()*sqr(xline.Length()));
	assert(x_z.Length() == w_z.Length());
	assert(xline.Length() == wline.Length());
	int cnt = 1;
	for (int i = 1; i <= xline.GetLen(); i++)
		for (int j = 1; j <= xline.GetLen(); j++)
			for (int k = 1; k <= x_z.GetLen(); ++k)
			{
				double z = x_z(k);
				integrationRule.integrationPoints(cnt).x = xline(i)*(1-z);
				integrationRule.integrationPoints(cnt).y = xline(j)*(1-z);
				integrationRule.integrationPoints(cnt).z = z;
				//the /8. is due to the transformation of [-1,1] to [0,1] 
				integrationRule.integrationPoints(cnt).weight = w_z(k) * sqr(1- z) * wline(i) * wline(j)/8.;
				cnt++;
			}
}
void IntegrationRule::DefineIntegrationRuleSquareAnisotropic(IntegrationRule & integrationRule, int ruleOrder_x, int ruleOrder_y)
{
	// we use a ready function, which provides a one-dimensional integration rule
	// we use different integration rules for x and y direction
	Vector xx, xy;
	Vector wx, wy;
	GetIntegrationRule(xx, wx, ruleOrder_x);
	GetIntegrationRule(xy, wy, ruleOrder_y);

	// and now we create a 2D integration rule
	integrationRule.integrationPoints.SetLen(xx.Length() * xy.Length());
	int cnt = 1;
	for (int i1 = 1; i1 <= xx.GetLen(); i1++)
	{
		for (int i2 = 1; i2 <= xy.GetLen(); i2++)
		{
			integrationRule.integrationPoints(cnt).x = xx(i1);
			integrationRule.integrationPoints(cnt).y = xy(i2);
			integrationRule.integrationPoints(cnt).z = 0;
			integrationRule.integrationPoints(cnt).weight = wx(i1) * wy(i2);
			cnt++;
		}
	}
}