int read_ct_tran(struct patient_struct *ppatient, QString *Result) { FILE *f_tran = NULL; uint32_t file_typ, ser_head_length, block_length, ser_number, numb_of_slices; char pat_name[80], comm[80], date[80]; uint32_t trafo_type; uint32_t calculated; uint32_t is_axial; double marker[12][2]; double plate[16][2]; uint32_t missing; uint32_t all_slices; uint32_t elements_v_rev_mat; uint32_t i, j, n; double fov_by_2; double global_inv_mat[4][4]; mat44_t mat; mat44_t rev_mat; vector<mat44_t> v_mat, v_rev_mat; xyze Stereo_point_0; xyze Stereo_point_1; xyze Stereo_point_2; xyze Stereo_point_3; const int imax = 4; double Edge_point_a[imax] = { 0.0, 0.0, 1.0, 1.0 }; double Edge_point_b[imax] = { 0.0, 1023.0, 1.0, 1.0 }; double Edge_point_c[imax] = { 1023.0, 1023.0, 1.0, 1.0 }; double Edge_point_d[imax] = { 1023.0, 0.0, 1.0, 1.0 }; double last_col_glo_matrix[imax] = { 0.0, 0.0, 0.0, 1.0 }; QTextStream ts(Result, IO_WriteOnly); ts << "<B>Loading " << ppatient->Tra_File; if ((f_tran = fopen(ppatient->Tra_File, "rb")) == NULL) { ts << ": failed!</B><br><br>"; return 1; } // read transformation header if (fread(&file_typ, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_52 failed in ReadSTP3.cpp"); } if (fread(&ser_head_length, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_53 failed in ReadSTP3.cpp"); } if (fread(&block_length, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_54 failed in ReadSTP3.cpp"); } if (fread(pat_name, 1, 80, f_tran) != 1) { fprintf(stderr, "fread_55 failed in ReadSTP3.cpp"); } if (fread(comm, 1, 80, f_tran) != 1) { fprintf(stderr, "fread_56 failed in ReadSTP3.cpp"); } if (fread(date, 1, 80, f_tran) != 1) { fprintf(stderr, "fread_57 failed in ReadSTP3.cpp"); } if (fread(&ser_number, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_58 failed in ReadSTP3.cpp"); } if (fread(&numb_of_slices, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_59 failed in ReadSTP3.cpp"); } // read transformation for each slice for (j = 1; j < numb_of_slices + 1; j++) { fseek(f_tran, block_length * j + ser_head_length, SEEK_SET); if (fread(&trafo_type, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_60 failed in ReadSTP3.cpp"); } if (fread(&calculated, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_61 failed in ReadSTP3.cpp"); } if (fread(&is_axial, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_62 failed in ReadSTP3.cpp"); } if (fread(marker, sizeof(marker), 1, f_tran) != sizeof(marker)) { fprintf(stderr, "fread_63 failed in ReadSTP3.cpp"); } if (fread(plate, sizeof(plate), 1, f_tran) != sizeof(plate)) { fprintf(stderr, "fread_64 failed in ReadSTP3.cpp"); } if (fread(&missing, 4, 1, f_tran) != 4) { fprintf(stderr, "fread_65 failed in ReadSTP3.cpp"); } if (fread(mat.mat, sizeof(mat.mat), 1, f_tran) != sizeof(mat.mat)) { fprintf(stderr, "fread_66 failed in ReadSTP3.cpp"); } if (fread(rev_mat.mat, sizeof(rev_mat.mat), 1, f_tran) != sizeof(rev_mat.mat)) { fprintf(stderr, "fread_67 failed in ReadSTP3.cpp"); } v_mat.push_back(mat); v_rev_mat.push_back(rev_mat); } fclose(f_tran); all_slices = v_mat.size(); elements_v_rev_mat = v_rev_mat.size(); fov_by_2 = ppatient->Pixel_size * ppatient->Resolution / 2.0; n = ppatient->No_Slices * 4; // define for geting the glogal transformation matrix, using the // singular value decomposition NR::svdcmp(x,w,v), and backsustitution NR::svbksb(x,w,v,b_x,x_x); // here we used matrix defined in Numerical Recipes because are dinamics(we dont know how many members have) Mat_DP x(n, 4), u(n, 4), v(4, 4); Vec_DP w(4), b(n); Vec_DP b_x(n), b_y(n), b_z(n); Vec_DP x_x(n), x_y(n), x_z(n); // define for geting the inverse glogal transformation matrix, using the Lower Up decomposition // NR::ludcmp(global_mat,indx,d), and backsustitution NR::lubksb(global_mat,indx,col); Mat_DP global_mat(4, 4); Vec_DP col(4); Vec_INT indx(4); DP d; for (i = 0; i < all_slices; i++) { // image coordinates x[i * 4 + 0][0] = fov_by_2; x[i * 4 + 0][1] = fov_by_2; x[i * 4 + 0][2] = ppatient->Z_Table[i]; x[i * 4 + 0][3] = 1.0; x[i * 4 + 1][0] = fov_by_2; x[i * 4 + 1][1] = -fov_by_2; x[i * 4 + 1][2] = ppatient->Z_Table[i]; x[i * 4 + 1][3] = 1.0; x[i * 4 + 2][0] = -fov_by_2; x[i * 4 + 2][1] = -fov_by_2; x[i * 4 + 2][2] = ppatient->Z_Table[i]; x[i * 4 + 2][3] = 1.0; x[i * 4 + 3][0] = -fov_by_2; x[i * 4 + 3][1] = fov_by_2; x[i * 4 + 3][2] = ppatient->Z_Table[i]; x[i * 4 + 3][3] = 1.0; // Stereotactic coordinates Stereo_point_0.x = 0.0; Stereo_point_0.y = 0.0; Stereo_point_0.z = 0.0; Stereo_point_1.x = 0.0; Stereo_point_1.y = 0.0; Stereo_point_1.z = 0.0; Stereo_point_2.x = 0.0; Stereo_point_2.y = 0.0; Stereo_point_2.z = 0.0; Stereo_point_3.x = 0.0; Stereo_point_3.y = 0.0; Stereo_point_3.z = 0.0; for (int f = 0; f <= 3; f++) { Stereo_point_0.x += v_mat[i].mat[f][1] * Edge_point_a[f]; Stereo_point_0.y += v_mat[i].mat[f][2] * Edge_point_a[f]; Stereo_point_0.z += v_mat[i].mat[f][3] * Edge_point_a[f]; Stereo_point_0.err = 1.0; // [0.0, 0.0, 1.0, 1,0] Stereo_point_1.x += v_mat[i].mat[f][1] * Edge_point_b[f]; Stereo_point_1.y += v_mat[i].mat[f][2] * Edge_point_b[f]; Stereo_point_1.z += v_mat[i].mat[f][3] * Edge_point_b[f]; Stereo_point_1.err = 1.0; // [0.0, 1024.0, 1.0, 1,0] Stereo_point_2.x += v_mat[i].mat[f][1] * Edge_point_c[f]; Stereo_point_2.y += v_mat[i].mat[f][2] * Edge_point_c[f]; Stereo_point_2.z += v_mat[i].mat[f][3] * Edge_point_c[f]; Stereo_point_2.err = 1.0; // [1024.0, 1024.0, 1.0, 1,0] Stereo_point_3.x += v_mat[i].mat[f][1] * Edge_point_d[f]; Stereo_point_3.y += v_mat[i].mat[f][2] * Edge_point_d[f]; Stereo_point_3.z += v_mat[i].mat[f][3] * Edge_point_d[f]; Stereo_point_3.err = 1.0; // [1024.0, 0.0, 1.0, 1,0] } b_x[i * 4 + 0] = Stereo_point_0.x; b_x[i * 4 + 1] = Stereo_point_1.x; b_x[i * 4 + 2] = Stereo_point_2.x; b_x[i * 4 + 3] = Stereo_point_3.x; b_y[i * 4 + 0] = Stereo_point_0.y; b_y[i * 4 + 1] = Stereo_point_1.y; b_y[i * 4 + 2] = Stereo_point_2.y; b_y[i * 4 + 3] = Stereo_point_3.y; b_z[i * 4 + 0] = Stereo_point_0.z; b_z[i * 4 + 1] = Stereo_point_1.z; b_z[i * 4 + 2] = Stereo_point_2.z; b_z[i * 4 + 3] = Stereo_point_3.z; } // solve linear equation NR::svdcmp(x, w, v); // here we make the decomposition of the matrix X (image coordinate,for the for points in each slices)! NR::svbksb(x, w, v, b_x, x_x); NR::svbksb(x, w, v, b_y, x_y); NR::svbksb(x, w, v, b_z, x_z); // transformation matrix for (i = 0; i < 4; i++) { ppatient->Global_Tra_Matrix[i][0] = x_x[i]; ppatient->Global_Tra_Matrix[i][1] = x_y[i]; ppatient->Global_Tra_Matrix[i][2] = x_z[i]; ppatient->Global_Tra_Matrix[i][3] = last_col_glo_matrix[i]; for (j = 0; j < 4; j++) global_mat[i][j] = ppatient->Global_Tra_Matrix[i][j]; } // calculate inverse matrix NR::ludcmp(global_mat, indx, d); for (j = 0; j < 4; j++) { for (i = 0; i < 4; i++) col[i] = 0.0; col[j] = 1.0; NR::lubksb(global_mat, indx, col); for (i = 0; i < 4; i++) global_inv_mat[i][j] = col[i]; } // print transformation info ts << ": Ok</B>"; ts << "<br><br><B>Transformation Info</B>"; // <br> te salta una linea, con el primer B me lo escribiria to en negro pa especificar q solo queremos la linea esa se pone al final </B> ts << "<pre>"; // si omito esta linea me escribe la dos matrices juntas sin ningun sentido!, y pq el otro no pasa na cuando se omite, ver # ts << "Mat = <br>"; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) ppatient->Rev_Global_Tra_Matrix[i][j] = global_inv_mat[i][j]; ts << " " << ppatient->Global_Tra_Matrix[i][0] << " " << ppatient->Global_Tra_Matrix[i][1] << " " << ppatient->Global_Tra_Matrix[i][2] << " " << ppatient->Global_Tra_Matrix[i][3] << "<br>"; } ts << "RevMat = <br>"; for (i = 0; i < 4; i++) ts << " " << ppatient->Rev_Global_Tra_Matrix[i][0] << " " << ppatient->Rev_Global_Tra_Matrix[i][1] << " " << ppatient->Rev_Global_Tra_Matrix[i][2] << " " << ppatient->Rev_Global_Tra_Matrix[i][3] << "<br>"; ts << "<br></pre>"; return 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; } */ }