Re: [ibsimu-forum] Secondary emission off STL surfaces
Status: Beta
Brought to you by:
tvkalvas
|
From: Kalvas, T. <tan...@jy...> - 2019-04-24 21:25:17
|
I made the algorithm I was planning. My tests of presented some nasty pathological cases I did not expect, but I fixed also those. And while debugging all of this I noticed that I had made a callback for exactly what you want already some years ago. So there is a new development version of IBSimu available, which contains this update, but you don't really need it.
Use TrajectorySurfaceCollisionCallback, which gives you the index of the surface triangle, where your particle hit. Using the index with surface_triangle_normal() you get the normal you want. Example with both this existing method and the new development is attached below.
Taneli
--
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <iomanip>
#include "epot_gssolver.hpp"
#include "epot_umfpacksolver.hpp"
#include "epot_bicgstabsolver.hpp"
#include "particledatabase.hpp"
#include "geometry.hpp"
#include "convergence.hpp"
#include "func_solid.hpp"
#include "epot_efield.hpp"
#include "meshvectorfield.hpp"
#include "ibsimu.hpp"
#include "error.hpp"
#include "particlediagplotter.hpp"
#include "fielddiagplotter.hpp"
#include "gtkplotter.hpp"
#include "geomplotter.hpp"
using namespace std;
double r0 = 0.1;
// Make a sphere
bool solid1( double x, double y, double z )
{
double r = sqrt(x*x + y*y + z*z);
return( r < r0 );
}
class TestSurCB : public TrajectorySurfaceCollisionCallback {
Geometry &_geom;
public:
TestSurCB( Geometry &geom )
: _geom(geom) {
}
virtual ~TestSurCB() {
}
virtual void operator()( ParticleBase *particle, ParticlePBase *x, uint32_t tri, double s, double t ) {
std::cout << "Surface Callback!\n";
Vec3D n = _geom.surface_triangle_normal( tri );
std::cout << "normal = " << n << "\n";
}
};
class TestCB : public TrajectoryEndCallback {
Geometry &_geom;
public:
TestCB( Geometry &geom )
: _geom(geom) {
}
virtual ~TestCB() {
}
virtual void operator()( ParticleBase *particle, class ParticleDataBase *pdb ) {
std::cout << "End Callback!\n";
Particle3D *p3d = (Particle3D *)( particle );
Vec3D loc = p3d->location();
Vec3D normal = _geom.surface_triangle_normal( loc );
std::cout << "normal = " << normal << "\n";
}
};
void simu( int argc, char **argv )
{
double h = 0.01;
Int3D size( floor(0.15/h)+1,
floor(0.15/h)+1,
floor(0.15/h)+1 );
Geometry geom( MODE_3D, size, Vec3D(0,0,0), h );
Solid *s1 = new FuncSolid( solid1 );
geom.set_solid( 7, s1 );
geom.set_boundary( 1, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 2, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 3, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 4, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 5, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 6, Bound(BOUND_DIRICHLET, 0.0) );
geom.set_boundary( 7, Bound(BOUND_DIRICHLET, 0.0) );
geom.build_mesh();
geom.build_surface();
EpotField epot( geom );
MeshScalarField scharge( geom );
MeshVectorField bfield;
EpotEfield efield( epot );
TestCB tcb( geom );
TestSurCB tsurcb( geom );
ParticleDataBase3D pdb( geom );
pdb.set_surface_collision( true );
pdb.set_trajectory_end_callback( &tcb );
pdb.set_trajectory_surface_collision_callback( &tsurcb );
pdb.add_particle( 1, 1, 1, ParticleP3D(0,
geom.max(0)-1e-6,-1e6,
geom.max(1)-1e-6,-1e6,
geom.max(2)-1e-6,-1e6) );
pdb.iterate_trajectories( scharge, efield, bfield );
}
int main( int argc, char **argv )
{
try {
ibsimu.set_message_threshold( MSG_VERBOSE, 1 );
ibsimu.set_message_threshold( MSG_DEBUG_GENERAL, 1 );
ibsimu.set_thread_count( 4 );
simu( argc, argv );
} catch( Error e ) {
e.print_error_message( ibsimu.message( 0 ) );
exit( 1 );
}
return( 0 );
}
--
Taneli Kalvas
Ph.D., Senior researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax: +358-14-617-411
Email: tan...@jy...
________________________________________
From: Scott Lawrie - UKRI STFC <sco...@st...>
Sent: Tuesday, April 23, 2019 4:28:35 PM
To: Kalvas, Taneli; ibs...@li...
Subject: RE: Secondary emission off STL surfaces
Thanks for getting back to me. I'm glad it's a known issue. I had poked around with surface_triangle_normal(a) but didn't know how to find (a), so your plan makes sense. Do you think it'll be a library fix (needing an IBSimu version update) or a mod to the secondary electron code example? You shouldn't be working in the evening, you hero! However if you're willing and can come up with something by the end of the week that would be amazing, thanks so much.
Scott.
-----Original Message-----
From: Kalvas, Taneli <tan...@jy...>
Sent: 23 April 2019 14:17
To: Lawrie, Scott (STFC,RAL,ISIS) <sco...@st...>; ibs...@li...
Subject: Re: Secondary emission off STL surfaces
Hi Scott,
I know. It is irritating. There is so much potential in the triangulation that is not implemented.
Geometry::surface_normal_3d() seems to be using the inside() method to probe for locations. If the geometry is produced by a load from a file the solids do not exist any more in memory. The advantage of the STL geometry is that it would be possible to implement the save. Current it seems that the save-routine of the STL just prints out "Warning: saving of STLSolid not implemented". Even though programming that would be very straightforward, I do not have the time currently.
Also, notice that the surface representation in Geometry (which is based on the mesh of the simulation and is therefore much faster than the STL) is not saved either. So after doing load on a geometry you need to call build_surface().
I think the best solution would be to implement an alternative method inside Geometry::surface_normal(), which would use surface representation built by build_surface() and return the normal of the closest triangle. Half of this exists already. There is a routine Geometry::surface_triangle_normal(a), where a points to the index of the triangle. The only part missing really is finding the right triangle.
Plan:
1. The user gives the coordinates to surface_normal(x).
2. Find mesh cell (i,j,k) using x.
3. Using surface_triangle_ptr(i,j,k), surface_trianglec(i,j,k) and surface_triangle(a) get access to triangle coordinates inside the cell 4. Transform the point coordinates to natural coordinates (u,v,w) of each triangle, where u and v are distance in the direction of the edges 12 and 13 and w is the distance from the plane of the triangle.
5. If u and v are normalized one can check if the point is within the triangle 0<u<1 and 0<v<1 and u+v<1. Some robustness factor added to these (1e-6). Normalize w to h and require |w|<1e-6 6. If a good triangle is found, return the normal of the triangle.
I would say that is about 2 hours of programming, corrected by factor of pi, giving 6.3 hours. I might have some time tonight. When do you need it?
Taneli
--
Taneli Kalvas
Ph.D., Senior researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax: +358-14-617-411
Email: tan...@jy...
________________________________________
From: Scott Lawrie - UKRI STFC <sco...@st...>
Sent: Tuesday, April 23, 2019 2:28:15 PM
To: ibs...@li...
Subject: [ibsimu-forum] Secondary emission off STL surfaces
Dear Taneli,
For years I have been using simple Boolean-defined solid geometries and using your excellent secondary electron emission code example. Part of that code calculates the surface normal at the particle collision location. I have now decided to bite the bullet and use STL imports and the 'save/load geometry' example, including set_surface_collision(true). The problem with STLs is that they are only surfaces, so there are no 'solids' really, meaning geom.surface_normal(loc) doesn't work. Please can you let me know how to modify the secondary emission code to work for STL geometries?
Thanks a lot,
Scott.
|