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; }
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); }
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); }
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; }
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; }
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; }
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; } */ }