コード例 #1
1
bool link_sparse_hessian(
	size_t                           size     , 
	size_t                           repeat   , 
	CppAD::vector<double>&           x        ,
	const CppAD::vector<size_t>&     row      ,
	const CppAD::vector<size_t>&     col      ,
	CppAD::vector<double>&           hessian  )
{
	// -----------------------------------------------------
	// setup
	typedef vector<double>              DblVector;
	typedef vector< std::set<size_t> >  SetVector;
	typedef CppAD::AD<double>           ADScalar;
	typedef vector<ADScalar>            ADVector;

	size_t i, j, k;
	size_t order = 0;         // derivative order corresponding to function
	size_t m = 1;             // number of dependent variables
	size_t n = size;          // number of independent variables
	size_t K = row.size();    // number of non-zeros in lower triangle
	ADVector   a_x(n);        // AD domain space vector
	ADVector   a_y(m);        // AD range space vector
	DblVector  w(m);          // double range space vector
	DblVector hes(K);         // non-zeros in lower triangle
	CppAD::ADFun<double> f;   // AD function object

	// weights for hessian calculation (only one component of f)
	w[0] = 1.;

	// use the unspecified fact that size is non-decreasing between calls
	static size_t previous_size = 0;
	bool print    = (repeat > 1) & (previous_size != size);
	previous_size = size;

	// declare sparsity pattern
# if USE_SET_SPARSITY
	SetVector sparsity(n);
# else
	typedef vector<bool>                BoolVector;
	BoolVector sparsity(n * n);
# endif
	// initialize all entries as zero
	for(i = 0; i < n; i++)
	{	for(j = 0; j < n; j++)
			hessian[ i * n + j] = 0.;
	}
	// ------------------------------------------------------
	extern bool global_retape;
	if( global_retape) while(repeat--)
	{	// choose a value for x 
		CppAD::uniform_01(n, x);
		for(j = 0; j < n; j++)
			a_x[j] = x[j];

		// declare independent variables
		Independent(a_x);	

		// AD computation of f(x)
		CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y);

		// create function object f : X -> Y
		f.Dependent(a_x, a_y);

		extern bool global_optimize;
		if( global_optimize )
		{	print_optimize(f, print, "cppad_sparse_hessian_optimize", size);
			print = false;
		}

		// calculate the Hessian sparsity pattern for this function
		calc_sparsity(sparsity, f);

		// structure that holds some of work done by SparseHessian
		CppAD::sparse_hessian_work work;

		// calculate this Hessian at this x
		f.SparseHessian(x, w, sparsity, row, col, hes, work);
		for(k = 0; k < K; k++)
		{	hessian[ row[k] * n + col[k] ] = hes[k];
			hessian[ col[k] * n + row[k] ] = hes[k];
		}
	}
	else
	{	// choose a value for x 
		CppAD::uniform_01(n, x);
		for(j = 0; j < n; j++)
			a_x[j] = x[j];

		// declare independent variables
		Independent(a_x);	

		// AD computation of f(x)
		CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y);

		// create function object f : X -> Y
		f.Dependent(a_x, a_y);

		extern bool global_optimize;
		if( global_optimize )
		{	print_optimize(f, print, "cppad_sparse_hessian_optimize", size);
			print = false;
		}

		// calculate the Hessian sparsity pattern for this function
		calc_sparsity(sparsity, f);

		// declare structure that holds some of work done by SparseHessian
		CppAD::sparse_hessian_work work;

		while(repeat--)
		{	// choose a value for x
			CppAD::uniform_01(n, x);

			// calculate sparsity at this x
			f.SparseHessian(x, w, sparsity, row, col, hes, work);

			for(k = 0; k < K; k++)
			{	hessian[ row[k] * n + col[k] ] = hes[k];
				hessian[ col[k] * n + row[k] ] = hes[k];
			}
		}
	}
	return true;
}
コード例 #2
0
ファイル: Figures.cpp プロジェクト: hksonngan/invols
void AddBox(Geometry*g, vec3 a,vec3 b,ivec3 br)
{
    Geometry tmp;
    if(a.x>b.x)swap(a.x,b.x);
    if(a.y>b.y)swap(a.y,b.y);
    if(a.z>b.z)swap(a.z,b.z);

    vec3 s = b - a;
    vec3 a_x(s.x/br.x,0,0);
    vec3 a_y(0,s.y/br.x,0);
    vec3 a_z(0,0,s.z/br.x);
    /*

    for(int i=0;i<=br.x;i++)
    for(int j=0;j<=br.x;j++)
    {
    	AddQuad(&tmp,a,a+a_y,a+a_x+a_y,a+a_x);
    	AddQuad(&tmp,b,b-a_x,b-a_x-a_y,b-a_y);

    	AddQuad(&tmp,a,a+a_x,a+a_x+a_z,a+a_z);
    	AddQuad(&tmp,b,b-a_z,b-a_x-a_z,b-a_x);

    	AddQuad(&tmp,b,b-a_y,b-a_z-a_y,b-a_z);
    	AddQuad(&tmp,a,a+a_z,a+a_z+a_y,a+a_y);
    }*/

    tmp.SetNormOutOf((a+b)*0.5f);
    g->Add(tmp);

}
コード例 #3
0
ファイル: Figures.cpp プロジェクト: hksonngan/invols
void AddBox(Geometry*g, vec3 a,vec3 b)
{
    Geometry tmp;
    if(a.x>b.x)swap(a.x,b.x);
    if(a.y>b.y)swap(a.y,b.y);
    if(a.z>b.z)swap(a.z,b.z);

    vec3 s = b - a;
    vec3 a_x(s.x,0,0);
    vec3 a_y(0,s.y,0);
    vec3 a_z(0,0,s.z);

    AddQuad(&tmp,a,a+a_y,a+a_x+a_y,a+a_x);
    AddQuad(&tmp,a,a+a_x,a+a_x+a_z,a+a_z);
    AddQuad(&tmp,a,a+a_z,a+a_z+a_y,a+a_y);

    AddQuad(&tmp,b,b-a_x,b-a_x-a_y,b-a_y);
    AddQuad(&tmp,b,b-a_z,b-a_x-a_z,b-a_x);
    AddQuad(&tmp,b,b-a_y,b-a_z-a_y,b-a_z);

    tmp.SetNormOutOf((a+b)*0.5f);
    g->Add(tmp);

}
コード例 #4
0
ファイル: sparse_jacobian.cpp プロジェクト: ruby-eigen/CppAD
bool link_sparse_jacobian(
	size_t                           size     ,
	size_t                           repeat   ,
	size_t                           m        ,
	const CppAD::vector<size_t>&     row      ,
	const CppAD::vector<size_t>&     col      ,
	      CppAD::vector<double>&     x        ,
	      CppAD::vector<double>&     jacobian ,
	      size_t&                    n_sweep  )
{
	if( global_atomic )
		return false;
# ifndef CPPAD_COLPACK_SPEED
	if( global_colpack )
		return false;
# endif
	// -----------------------------------------------------
	// setup
	typedef vector< std::set<size_t> >  SetVector;
	typedef CppAD::AD<double>           ADScalar;
	typedef CppAD::vector<ADScalar>     ADVector;

	size_t j;
	size_t order = 0;         // derivative order corresponding to function
	size_t n     = size;      // number of independent variables
	ADVector   a_x(n);        // AD domain space vector
	ADVector   a_y(m);        // AD range space vector y = g(x)
	CppAD::ADFun<double> f;   // AD function object

	// declare sparsity pattern
	SetVector  set_sparsity(m);
	BoolVector bool_sparsity(m * n);

	// ------------------------------------------------------
	if( ! global_onetape ) while(repeat--)
	{	// choose a value for x
		CppAD::uniform_01(n, x);
		for(j = 0; j < n; j++)
			a_x[j] = x[j];

		// declare independent variables
		Independent(a_x);

		// AD computation of f (x)
		CppAD::sparse_jac_fun<ADScalar>(m, n, a_x, row, col, order, a_y);

		// create function object f : X -> Y
		f.Dependent(a_x, a_y);

		if( global_optimize )
			f.optimize();

		// skip comparison operators
		f.compare_change_count(0);

		// calculate the Jacobian sparsity pattern for this function
		if( global_boolsparsity )
			calc_sparsity(bool_sparsity, f);
		else
			calc_sparsity(set_sparsity, f);

		// structure that holds some of the work done by SparseJacobian
		CppAD::sparse_jacobian_work work;
# ifdef CPPAD_COLPACK_SPEED
		if( global_colpack )
			work.color_method = "colpack";
# endif
		// calculate the Jacobian at this x
		// (use forward mode because m > n ?)
		if( global_boolsparsity) n_sweep = f.SparseJacobianForward(
				x, bool_sparsity, row, col, jacobian, work
		);
		else n_sweep = f.SparseJacobianForward(
				x, set_sparsity, row, col, jacobian, work
		);
	}
	else
	{	// choose a value for x
		CppAD::uniform_01(n, x);
		for(j = 0; j < n; j++)
			a_x[j] = x[j];

		// declare independent variables
		Independent(a_x);

		// AD computation of f (x)
		CppAD::sparse_jac_fun<ADScalar>(m, n, a_x, row, col, order, a_y);

		// create function object f : X -> Y
		f.Dependent(a_x, a_y);

		if( global_optimize )
			f.optimize();

		// skip comparison operators
		f.compare_change_count(0);

		// calculate the Jacobian sparsity pattern for this function
		if( global_boolsparsity )
			calc_sparsity(bool_sparsity, f);
		else
			calc_sparsity(set_sparsity, f);

		// structure that holds some of the work done by SparseJacobian
		CppAD::sparse_jacobian_work work;
# ifdef CPPAD_COLPACK_SPEED
		if( global_colpack )
			work.color_method = "colpack";
# endif
		while(repeat--)
		{	// choose a value for x
			CppAD::uniform_01(n, x);

			// calculate the Jacobian at this x
			// (use forward mode because m > n ?)
			if( global_boolsparsity ) n_sweep = f.SparseJacobianForward(
					x, bool_sparsity, row, col, jacobian, work
			);
			else n_sweep = f.SparseJacobianForward(
					x, set_sparsity, row, col, jacobian, work
			);
		}
	}
	return true;
}
コード例 #5
0
ファイル: opt_val_hes.hpp プロジェクト: bubuker/keggle_santa
int opt_val_hes(
	const BaseVector&   x     , 
	const BaseVector&   y     , 
	Fun                 fun   , 
	BaseVector&         jac   ,
	BaseVector&         hes   )
{	// determine the base type
	typedef typename BaseVector::value_type Base;

	// check that BaseVector is a SimpleVector class with Base elements
	CheckSimpleVector<Base, BaseVector>();

	// determine the AD vector type
	typedef typename Fun::ad_vector ad_vector;

	// check that ad_vector is a SimpleVector class with AD<Base> elements
	CheckSimpleVector< AD<Base> , ad_vector >();

	// size of the x and y spaces
	size_t n = size_t(x.size());
	size_t m = size_t(y.size());

	// number of terms in the summation
	size_t ell = fun.ell();

	// check size of return values
	CPPAD_ASSERT_KNOWN(
		size_t(jac.size()) == n || jac.size() == 0,
		"opt_val_hes: size of the vector jac is not equal to n or zero"
	);
	CPPAD_ASSERT_KNOWN(
		size_t(hes.size()) == n * n || hes.size() == 0,
		"opt_val_hes: size of the vector hes is not equal to n * n or zero"
	);

	// some temporary indices
	size_t i, j, k;

	// AD version of S_k(x, y)
	ad_vector s_k(1);

	// ADFun version of S_k(x, y)
	ADFun<Base> S_k;

	// AD version of x 
	ad_vector a_x(n);

	// AD version of y
	ad_vector a_y(n);

	if( jac.size() > 0  )
	{	// this is the easy part, computing the V^{(1)} (x) which is equal 
		// to \partial_x F (x, y) (see Thoerem 2 of the reference).

		// copy x and y to AD version
		for(j = 0; j < n; j++)
			a_x[j] = x[j];
		for(j = 0; j < m; j++)
			a_y[j] = y[j];

		// initialize summation
		for(j = 0; j < n; j++)
			jac[j] = Base(0.);

		// add in \partial_x S_k (x, y)
		for(k = 0; k < ell; k++)
		{	// start recording
			Independent(a_x);
			// record
			s_k[0] = fun.s(k, a_x, a_y);
			// stop recording and store in S_k
			S_k.Dependent(a_x, s_k);
			// compute partial of S_k with respect to x
			BaseVector jac_k = S_k.Jacobian(x);
			// add \partial_x S_k (x, y) to jac
			for(j = 0; j < n; j++)
				jac[j] += jac_k[j];			 
		}
	}
	// check if we are done
	if( hes.size() == 0 )
		return 0;

	/*
	In this case, we need to compute the Hessian. Using Theorem 1 of the
	reference:
		Y^{(1)}(x) = - F_yy (x, y)^{-1} F_yx (x, y)
	Using Theorem 2 of the reference:
		V^{(2)}(x) = F_xx (x, y) + F_xy (x, y)  Y^{(1)}(x) 
	*/
	// Base and AD version of xy
	BaseVector xy(n + m);
	ad_vector a_xy(n + m);
	for(j = 0; j < n; j++)
		a_xy[j] = xy[j] = x[j]; 
	for(j = 0; j < m; j++)
		a_xy[n+j] = xy[n+j] = y[j]; 

	// Initialization summation for Hessian of F
	size_t nm_sq = (n + m) * (n + m);
	BaseVector F_hes(nm_sq);
	for(j = 0; j < nm_sq; j++)
		F_hes[j] = Base(0.);
	BaseVector hes_k(nm_sq); 

	// add in Hessian of S_k to hes
	for(k = 0; k < ell; k++)
	{	// start recording
		Independent(a_xy);
		// split out x
		for(j = 0; j < n; j++)
			a_x[j] = a_xy[j];
		// split out y
		for(j = 0; j < m; j++)
			a_y[j] = a_xy[n+j];
		// record
		s_k[0] = fun.s(k, a_x, a_y);
		// stop recording and store in S_k
		S_k.Dependent(a_xy, s_k);
		// when computing the Hessian it pays to optimize the tape
		S_k.optimize();
		// compute Hessian of S_k 
		hes_k = S_k.Hessian(xy, 0);
		// add \partial_x S_k (x, y) to jac
		for(j = 0; j < nm_sq; j++)
			F_hes[j] += hes_k[j];			 
	}
	// Extract F_yx
	BaseVector F_yx(m * n);
	for(i = 0; i < m; i++)
	{	for(j = 0; j < n; j++)
			F_yx[i * n + j] = F_hes[ (i+n)*(n+m) + j ];
	} 
	// Extract F_yy
	BaseVector F_yy(n * m);
	for(i = 0; i < m; i++)
	{	for(j = 0; j < m; j++)
			F_yy[i * m + j] = F_hes[ (i+n)*(n+m) + j + n ];
	} 

	// compute - Y^{(1)}(x) = F_yy (x, y)^{-1} F_yx (x, y)
	BaseVector neg_Y_x(m * n);
	Base logdet;
	int signdet = CppAD::LuSolve(m, n, F_yy, F_yx, neg_Y_x, logdet);
	if( signdet == 0 )
		return signdet;

	// compute hes = F_xx (x, y) + F_xy (x, y)  Y^{(1)}(x) 
	for(i = 0; i < n; i++)
	{	for(j = 0; j < n; j++)
		{	hes[i * n + j] = F_hes[ i*(n+m) + j ];
			for(k = 0; k < m; k++)
				hes[i*n+j] -= F_hes[i*(n+m) + k+n] * neg_Y_x[k*n+j];
		}
	}
	return signdet;
}
コード例 #6
0
void fi::VPDetectionWrapper::validateVanishingPoint(const std::vector<std::vector< Eigen::Vector2f> > &computed_vp_hypothesis, const Eigen::Matrix3f &cam_calib, Eigen::Vector3f &final_robust_vp_x, Eigen::Vector3f &final_robust_vp_y)
{
	Eigen::Matrix3f inv_cam_calib = cam_calib.inverse(); 

	//trans from vps to rays through camera axis, see Z+H Chapter 8, more on single view geometry!
	unsigned int num_vps = computed_vp_hypothesis.size();
	std::vector< Eigen::Vector3f> computed_vp_hypothesis_x;
	std::vector< Eigen::Vector3f> computed_vp_hypothesis_y;
	std::vector< Eigen::Vector3f> computed_vp_hypothesis_z;
	for (unsigned int i = 0; i < num_vps; i++)
	{
		std::vector<Eigen::Vector2f> a_vp = computed_vp_hypothesis.at(i);

		Eigen::Vector2f a_x = a_vp.at(0);
		Eigen::Vector3f x_h, n_x;
		x_h(0) = a_x(0);
		x_h(1) = a_x(1);
		x_h(2) = 1;
		n_x = inv_cam_calib * x_h;
		n_x = n_x.normalized();
		computed_vp_hypothesis_x.push_back(n_x);

		Eigen::Vector2f a_y = a_vp.at(1);
		Eigen::Vector3f y_h, n_y;
		y_h(0) = a_y(0);
		y_h(1) = a_y(1);
		y_h(2) = 1;
		n_y = inv_cam_calib * y_h;
		n_y = n_y.normalized();
		computed_vp_hypothesis_y.push_back(n_y);

		Eigen::Vector2f a_z = a_vp.at(2);
		Eigen::Vector3f z_h, n_z;
		z_h(0) = a_z(0);
		z_h(1) = a_z(1);
		z_h(2) = 1;
		n_z = inv_cam_calib * z_h;
		n_z = n_z.normalized();
		computed_vp_hypothesis_z.push_back(n_z);
	}

	std::vector<Eigen::Vector3f> in_liers_x;
	std::vector<Eigen::Vector3f> in_liers_y;
	std::vector<Eigen::Vector3f> in_liers_z;
	bool found_inliers_x = getRansacInliers(computed_vp_hypothesis_x, in_liers_x);
	bool found_inliers_y = getRansacInliers(computed_vp_hypothesis_y, in_liers_y);
	bool found_inliers_z = getRansacInliers(computed_vp_hypothesis_z, in_liers_z);

	Eigen::VectorXf optimized_vp_x;
	Eigen::VectorXf optimized_vp_y;
	Eigen::VectorXf optimized_vp_z;
	leastQuaresVPFitting(in_liers_x, optimized_vp_x);
	leastQuaresVPFitting(in_liers_y, optimized_vp_y);
	leastQuaresVPFitting(in_liers_z, optimized_vp_z);
        std::cout<<"Vanishing Points Validated"<<std::endl;

	//test the angles and see if OK otherwise check again if truelly orthogonal
	Eigen::Vector3f vp_x (optimized_vp_x[3], optimized_vp_x[4], optimized_vp_x[5]);;
	Eigen::Vector3f vp_y (optimized_vp_y[3], optimized_vp_y[4], optimized_vp_y[5]);
	Eigen::Vector3f vp_z (optimized_vp_z[3], optimized_vp_z[4], optimized_vp_z[5]);

	Eigen::Vector3f vp_x_centroid (optimized_vp_x[0], optimized_vp_x[1], optimized_vp_x[2]);
	Eigen::Vector3f vp_y_centroid (optimized_vp_y[0], optimized_vp_y[1], optimized_vp_y[2]);
	Eigen::Vector3f vp_z_centroid (optimized_vp_z[0], optimized_vp_z[1], optimized_vp_z[2]);

	float angle_value_radiens_cxy = angleBetweenVectors(vp_x_centroid, vp_y_centroid);
	float angle_value_degrees_cxy = pcl::rad2deg(angle_value_radiens_cxy);
	float angle_value_radiens_cxz = angleBetweenVectors(vp_x_centroid, vp_z_centroid);
	float angle_value_degrees_cxz = pcl::rad2deg(angle_value_radiens_cxz);
	float angle_value_radiens_cyz = angleBetweenVectors(vp_y_centroid, vp_z_centroid);
	float angle_value_degrees_cyz = pcl::rad2deg(angle_value_radiens_cyz);

	float angle_value_radiens_xy = angleBetweenVectors(vp_x, vp_y);
	float angle_value_degrees_xy = pcl::rad2deg(angle_value_radiens_xy);
	float angle_value_radiens_xz = angleBetweenVectors(vp_x, vp_z);
	float angle_value_degrees_xz = pcl::rad2deg(angle_value_radiens_xz);
	float angle_value_radiens_yz = angleBetweenVectors(vp_y, vp_z);
	float angle_value_degrees_yz = pcl::rad2deg(angle_value_radiens_yz);

	//collect only the mean vps
	final_robust_vp_x = optimized_vp_x.tail<3> ();
	final_robust_vp_y = optimized_vp_y.tail<3> ();

	//final_robust_vp_x = vp_x_centroid;
	//final_robust_vp_y = vp_y_centroid;
}
コード例 #7
0
    void assemble( DeviceType & device,
                   TimeStepQuantitiesT & old_quantities,
                   TimeStepQuantitiesT & quantities,
                   viennashe::config const & conf,
                   viennashe::she::unknown_she_quantity<VertexT, EdgeT> const & quan,
                   MatrixType & A,
                   VectorType & b,
                   bool use_timedependence, bool quan_valid)
    {
      typedef typename DeviceType::mesh_type              MeshType;

      typedef typename viennagrid::result_of::facet<MeshType>::type                 FacetType;
      typedef typename viennagrid::result_of::cell<MeshType>::type                  CellType;

      typedef typename viennagrid::result_of::const_facet_range<MeshType>::type     FacetContainer;
      typedef typename viennagrid::result_of::iterator<FacetContainer>::type        FacetIterator;

      typedef typename viennagrid::result_of::const_cell_range<MeshType>::type      CellContainer;
      typedef typename viennagrid::result_of::iterator<CellContainer>::type         CellIterator;

      typedef typename viennagrid::result_of::const_facet_range<CellType>::type     FacetOnCellContainer;
      typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type  FacetOnCellIterator;

      typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type     CellOnFacetContainer;
      typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type                            CellOnFacetIterator;

      typedef viennashe::math::sparse_matrix<double>   CouplingMatrixType;

      typedef typename viennashe::she::timestep_quantities<DeviceType>::unknown_quantity_type      SpatialUnknownType;

      std::vector< scattering_base<DeviceType> * > scattering_processes;

      if (conf.with_traps())
      {
        if (! conf.with_electrons() || ! conf.with_holes())
          throw viennashe::unavailable_feature_exception("Trapping without considering electrons or holes is not supported!");
        if ( conf.get_electron_equation() != viennashe::EQUATION_SHE)
          throw viennashe::unavailable_feature_exception("Trapping without SHE for electrons is not supported!");
        if ( conf.get_hole_equation() != viennashe::EQUATION_SHE)
          throw viennashe::unavailable_feature_exception("Trapping without SHE for holes is not supported!");
      }

//      try
//      {
        MeshType const & mesh = device.mesh();

        SpatialUnknownType const &     potential =     quantities.get_unknown_quantity(viennashe::quantity::potential());
        SpatialUnknownType const & old_potential = old_quantities.get_unknown_quantity(viennashe::quantity::potential());  //TODO: Take old timestep

        viennashe::she::unknown_she_quantity<VertexT, EdgeT> const & old_quan = old_quantities.she_quantity(quan.get_name());

        //
        // Set up scatter matrices:
        //
        const std::size_t L_max = static_cast<std::size_t>(conf.max_expansion_order());
        const std::size_t num_harmonics = std::size_t(L_max+1) * std::size_t(L_max+1);
        CouplingMatrixType scatter_op_in(num_harmonics, num_harmonics);
        CouplingMatrixType scatter_op_out(num_harmonics, num_harmonics);

        for (std::size_t i=0; i < std::size_t(L_max+1) * std::size_t(L_max+1); ++i)
          scatter_op_out(i,i) += 1.0;
        scatter_op_in(0,0) += 1.0;

        //// preprocessing: compute coefficients a_{l,m}^{l',m'} and b_{l,m}^{l',m'}
        std::size_t Lmax = static_cast<std::size_t>(conf.max_expansion_order());            //maximum expansion order
        std::size_t coupling_rows = static_cast<std::size_t>((Lmax+1) * (Lmax+1));
        std::size_t coupling_cols = coupling_rows;

        log::debug<log_assemble_all>() << "* assemble_all(): Computing coupling matrices..." << std::endl;
        CouplingMatrixType identity(coupling_rows, coupling_cols);
        for (std::size_t i=0; i<coupling_rows; ++i)
          for (std::size_t j=0; j<coupling_cols; ++j)
            identity(i,j) = (i == j) ? 1.0 : 0.0;

        CouplingMatrixType a_x(coupling_rows, coupling_cols);
        CouplingMatrixType a_y(coupling_rows, coupling_cols);
        CouplingMatrixType a_z(coupling_rows, coupling_cols);


        CouplingMatrixType b_x(coupling_rows, coupling_cols);
        CouplingMatrixType b_y(coupling_rows, coupling_cols);
        CouplingMatrixType b_z(coupling_rows, coupling_cols);

        //note: interchanged coordinates
        fill_coupling_matrices(a_x, a_y, a_z,
                               b_x, b_y, b_z,
                               static_cast<int>(Lmax));

        CouplingMatrixType a_x_transposed = a_x.trans();
        CouplingMatrixType a_y_transposed = a_y.trans();
        CouplingMatrixType a_z_transposed = a_z.trans();

        CouplingMatrixType b_x_transposed = b_x.trans();
        CouplingMatrixType b_y_transposed = b_y.trans();
        CouplingMatrixType b_z_transposed = b_z.trans();

        if (log_assemble_all::enabled && log_assemble_all::debug)
        {
          log::debug<log_assemble_all>() << "a_x: " << a_x << std::endl;
          log::debug<log_assemble_all>() << "a_y: " << a_y << std::endl;
          log::debug<log_assemble_all>() << "a_z: " << a_z << std::endl;
          log::debug<log_assemble_all>() << "b_x: " << b_x << std::endl;
          log::debug<log_assemble_all>() << "b_y: " << b_y << std::endl;
          log::debug<log_assemble_all>() << "b_z: " << b_z << std::endl;

          log::debug<log_assemble_all>() << "identity: " << identity << std::endl;

          log::debug<log_assemble_all>() << "scatter_op_out: " << scatter_op_out << std::endl;
          log::debug<log_assemble_all>() << "scatter_op_in: "  << scatter_op_in << std::endl;
        }

        //
        // Setup vector of scattering processes:
        //


        if (conf.scattering().acoustic_phonon().enabled())
        {
          log::debug<log_assemble_all>() << "assemble(): Acoustic phonon scattering is ENABLED!" << std::endl;
          scattering_processes.push_back(new acoustic_phonon_scattering<DeviceType>(device, conf));
        }

        if (conf.scattering().optical_phonon().enabled())
        {
          log::debug<log_assemble_all>() << "assemble(): Optical phonon scattering is ENABLED!" << std::endl;
          scattering_processes.push_back(new optical_phonon_scattering<DeviceType>(device, conf, conf.energy_spacing()));
        }

        if (conf.scattering().ionized_impurity().enabled())
        {
          log::debug<log_assemble_all>() << "assemble(): Ionized impurity scattering is ENABLED!" << std::endl;
          scattering_processes.push_back(new ionized_impurity_scattering<DeviceType>(device, conf));
        }

        if (conf.scattering().impact_ionization().enabled())
        {
          // Warn the user if we already know that he/she is going to simulate bullshit.
          if ( ! conf.with_holes() || conf.get_hole_equation() != viennashe::EQUATION_SHE )
            log::warn() << std::endl << "WARNING: II scattering enabled, but 'BTE for holes' is disabled! Expect inconsistent results!" << std::endl;
          if ( ! conf.with_electrons() || conf.get_electron_equation() != viennashe::EQUATION_SHE )
            log::warn() << std::endl << "WARNING: II scattering enabled, but 'BTE for electrons' is disabled! Expect inconsistent results!" << std::endl;

          scattering_processes.push_back(new impact_ionization_scattering<DeviceType>(device, conf));
        }

        if (conf.with_traps() && conf.scattering().trapped_charge().enabled())
        {
          log::debug<log_assemble_all>() << "assemble(): Trapped charge scattering is ENABLED!" << std::endl;
          scattering_processes.push_back(new trapped_charge_scattering<DeviceType, TimeStepQuantitiesT>(device, conf, quantities));
        }

        typedef typename viennashe::electric_field_wrapper<DeviceType, SpatialUnknownType> ElectricFieldAccessor;
        ElectricFieldAccessor Efield(device, potential);

        if (conf.scattering().surface().enabled())
        {
          log::debug<log_assemble_all>() << "assemble(): Surface roughness scattering is ENABLED!" << std::endl;
          scattering_processes.push_back(new surface_scattering<DeviceType, ElectricFieldAccessor>(device, conf, Efield));
        }


        //
        // Assemble SHE system:
        //    - scattering operators on vertices
        //    - free streaming operator on vertices
        //    - scattering operators on edges
        //    - free streaming operator on edges
        //    - any other stuff (traps on cells, etc.)
        //

        if (quan_valid && conf.scattering().electron_electron() && conf.with_electrons())
        {
          log::debug<log_assemble_all>() << "assemble(): Electron electron scattering is ENABLED!" << std::endl;
          assemble_ee_scattering(device, conf, quan, old_quan, A, b);
        }

        //
        // Step 1: Assemble on even nodes
        //
        log::debug<log_assemble_all>() << "* assemble_all(): Even unknowns..." << std::endl;

        CellContainer cells(mesh);
        for (CellIterator cit = cells.begin();
            cit != cells.end();
            ++cit)
        {
          log::debug<log_assemble_all>() << "* assemble_all(): Assembling on cell " << *cit << std::endl;

          for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
          {
            if (log_assemble_all::enabled)
              log::debug<log_assemble_all>() << "* assemble_all(): Assembling on energy index " << index_H << std::endl;

            assemble_boundary_on_box(device, conf, quan,
                                     A, b,
                                     *cit, index_H,
                                     identity);

            if (viennashe::materials::is_conductor(device.get_material(*cit)))
              continue;

            //
            // Scattering operator Q{f}
            //
            assemble_scattering_operator_on_box( scattering_processes,
                                                 device, conf, quan,
                                                 A, b,
                                                 *cit, index_H,
                                                 scatter_op_in, scatter_op_out);
          }

          //
          // Free streaming operator L{f}
          //

          // iterate over neighbor cells holding the odd unknowns:
          FacetOnCellContainer facets_on_cell(*cit);
          for (FacetOnCellIterator focit = facets_on_cell.begin();
              focit != facets_on_cell.end();
              ++focit)
          {
            if (log_assemble_all::enabled)
              log::debug<log_assemble_all>() << "* assemble_all(): Assembling coupling with facet " << *focit << std::endl;

            CellType const *other_cell_ptr = util::get_other_cell_of_facet(mesh, *focit, *cit);
            if (!other_cell_ptr) continue;  //Facet is on the boundary of the simulation domain -> homogeneous Neumann conditions

            CouplingMatrixType coupling_matrix_diffusion = coupling_matrix_in_direction(a_x, a_y, a_z,
                                                                                        *cit,
                                                                                        *other_cell_ptr,
                                                                                        quan.get_carrier_type_id());

            // note that the sign change due to MEDS is included in the choice of the normal vector direction (order of vertex vs. other_vertex):
            // - B \cdot n   for even unknowns,
            // + B \cdot n   for odd unknowns
            CouplingMatrixType coupling_matrix_drift = coupling_matrix_in_direction(b_x, b_y, b_z, *other_cell_ptr, *cit, quan.get_carrier_type_id());

            for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
            {
              assemble_free_streaming_operator_on_box( device, conf, quan,
                                                       A, b,
                                                       *cit, *focit, index_H,
                                                       coupling_matrix_diffusion,
                                                       coupling_matrix_drift,
                                                       false);
            }
          } //for edges

          //
          // Time dependence df/dt (and possibly df/dH * dH/dt)
          //
          if (use_timedependence)
          {
            for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
            {
              viennashe::she::assemble_timederivative(device, conf, quan, old_quan,
                                                      A, b,
                                                      *cit, index_H,
                                                      identity,
                                                      potential,
                                                      old_potential);
            }
          }
        } //for cells


        //
        // Step 2: Assemble on odd 'nodes' (i.e. facets). TODO: Resolve code duplication w.r.t. above
        //
        log::info<log_assemble_all>() << "* assemble_all(): Odd unknowns..." << std::endl;

        FacetContainer facets(mesh);
        for (FacetIterator fit = facets.begin();
             fit != facets.end();
             ++fit)
        {
          if (log_assemble_all::enabled)
            log::debug<log_assemble_all>() << "* assemble_all(): Assembling on facet " << *fit << std::endl;

          for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
          {
            if (log_assemble_all::enabled)
              log::debug<log_assemble_all>() << "* assemble_all(): Assembling on energy index " << index_H << std::endl;

            //
            // Scattering operator Q{f}
            //
            assemble_scattering_operator_on_box(scattering_processes,
                                                device, conf, quan,
                                                A, b,
                                                *fit, index_H,
                                                scatter_op_in, scatter_op_out);
          }

          //
          // Free streaming operator L{f}
          //

          // iterate over cells of facet
          CellOnFacetContainer cells_on_facet(mesh, fit.handle());
          for (CellOnFacetIterator cofit  = cells_on_facet.begin();
                                   cofit != cells_on_facet.end();
                                 ++cofit)
          {
            if (log_assemble_all::enabled)
              log::debug<log_assemble_all>() << "* assemble_all(): Assembling coupling with cell " << *cofit << std::endl;

            CellType const *other_cell_ptr = util::get_other_cell_of_facet(mesh, *fit, *cofit);
            if (!other_cell_ptr) continue;  //Facet is on the boundary of the simulation domain -> homogeneous Neumann conditions

            CouplingMatrixType coupling_matrix_diffusion = coupling_matrix_in_direction(a_x_transposed, a_y_transposed, a_z_transposed,
                                                                                        *other_cell_ptr,
                                                                                        *cofit,
                                                                                        quan.get_carrier_type_id());

            // note that the sign change due to MEDS is included in the choice of the normal vector direction (order of vertex vs. other_vertex):
            // - B \cdot n   for even unknowns,
            // + B \cdot n   for odd unknowns
            CouplingMatrixType coupling_matrix_drift = coupling_matrix_in_direction(b_x_transposed, b_y_transposed, b_z_transposed, *other_cell_ptr, *cofit, quan.get_carrier_type_id());

            for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
            {
              assemble_free_streaming_operator_on_box( device, conf, quan,
                                                       A, b,
                                                       *cofit, *fit, index_H,
                                                       coupling_matrix_diffusion,
                                                       coupling_matrix_drift,
                                                       true);
            }
          } //for vertices

          //
          // Time dependence df/dt (and possibly df/dH * dH/dt)
          //
          if (use_timedependence)
          {
            for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
            {
              viennashe::she::assemble_timederivative(device, conf, quan, old_quan,
                                                      A, b,
                                                      *fit, index_H,
                                                      identity,
                                                      potential,
                                                      old_potential);
            }
          }

        } //for facets


        // Assemble traps on cells (to be integrated into the assembly above):
        if (conf.with_traps())
        {
          log::debug<log_assemble_all>() << "assemble(): Assembly for traps ..." << std::endl;
          viennashe::she::assemble_traps(device, quantities, conf, quan, A, b);
        }

        //
        // Cleanup:
        //
        for (std::size_t i=0; i<scattering_processes.size(); ++i)
        {
          if ( scattering_processes[i] ) delete scattering_processes[i];
          scattering_processes[i] = 0;
        }
/*      }
      catch (...)
      {
        //
        // Cleanup:
        //
        for (std::size_t i=0; i<scattering_processes.size(); ++i)
          if ( scattering_processes[i] ) delete scattering_processes[i];
        // Rethrow
        throw;
      }
*/

    }