Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/visuals/particles.c
3203 views
1
/*****************************************************************************
2
*
3
* Elmer, A Finite Element Software for Multiphysical Problems
4
*
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
*
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 2
10
* of the License, or (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program (in file fem/GPL-2); if not, write to the
19
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
* Boston, MA 02110-1301, USA.
21
*
22
*****************************************************************************/
23
24
/*******************************************************************************
25
*
26
* The character of the routines in this file.
27
*
28
*******************************************************************************
29
*
30
* Author: Juha Ruokolainen
31
*
32
* Address: CSC - IT Center for Science Ltd.
33
* Keilaranta 14, P.O. BOX 405
34
* 02101 Espoo, Finland
35
* Tel. +358 0 457 2723
36
* Telefax: +358 0 457 2302
37
* EMail: [email protected]
38
*
39
* Date: 1 May 1996
40
*
41
* Modified by:
42
*
43
* Date of modification:
44
*
45
******************************************************************************/
46
47
#include "../elmerpost.h"
48
49
50
typedef struct particle_s
51
{
52
scalar_t *VectorData[3];
53
scalar_t *ColorData;
54
55
int NofParticles;
56
scalar_t *ParticleData[5];
57
58
int SaveNofParticles;
59
60
double OutDT,MaxDT,Tolerance;
61
62
material_t *Material;
63
colormap_t *ColorMap;
64
65
arrow_style_t ArrowStyle;
66
67
double *X,*Y,*Z,*C,*I;
68
69
int Advance;
70
particle_integ_policy_t IntegPolicy;
71
particle_integ_method_t IntegMethod;
72
73
particle_style_t Style;
74
75
int LineQuality;
76
double LineWidth;
77
line_style_t LineStyle;
78
} particle_t;
79
80
extern int CurrentTimeStep;
81
82
static double vis_particles_interpolate
83
(
84
particle_t *particles, element_model_t *model, int n, double *velo, double t, double x, double y,double z
85
)
86
{
87
static double NX[ELM_MAX_ELEMENT_NODES];
88
static double NY[ELM_MAX_ELEMENT_NODES];
89
static double NZ[ELM_MAX_ELEMENT_NODES];
90
static double NF[ELM_MAX_ELEMENT_NODES];
91
92
double u,v,w;
93
94
double *XC = &model->NodeArray[0];
95
double *YC = &model->NodeArray[model->NofNodes];
96
double *ZC = &model->NodeArray[model->NofNodes*2];
97
98
int i,j,k,k0,k1,*T;
99
100
element_type_t *elmt;
101
element_t *elements = model->Elements;
102
103
if ( particles->ParticleData[4]->f[n] < 0 ) return 0.0;
104
105
k0 = particles->ParticleData[4]->f[n];
106
k1 = particles->ParticleData[4]->f[n] - 1;
107
108
t /= particles->OutDT;
109
110
for( j=0; j<model->NofElements; j++ )
111
{
112
if ( j & 1 )
113
{
114
if ( k0 >= model->NofElements ) i = k1--; else i = k0++;
115
} else {
116
if ( k1 < 0 ) i = k0++; else i = k1--;
117
}
118
119
T = elements[i].Topology;
120
elmt = elements[i].ElementType;
121
122
if ( !elmt->PointInside )
123
{
124
fprintf(
125
stderr, "WARNING: Particles not implemented for element type: [%s]. Element ignored.\n",
126
elmt->ElementName
127
);
128
continue;
129
}
130
131
for( k=0; k<elmt->NumberOfNodes; k++ )
132
{
133
NX[k] = XC[T[k]];
134
NY[k] = YC[T[k]];
135
NZ[k] = ZC[T[k]];
136
}
137
138
if ( !(*elmt->PointInside)( NX,NY,NZ,x,y,z,&u,&v,&w ) ) continue;
139
140
if ( CurrentTimeStep == model->NofTimesteps-1 )
141
{
142
for( k=0; k<elmt->NumberOfNodes; k++ )
143
{
144
NF[k] = velo[CurrentTimeStep*model->NofNodes + T[k]];
145
}
146
}
147
else
148
{
149
for( k=0; k<elmt->NumberOfNodes; k++ )
150
{
151
NF[k] = (1-t)*velo[CurrentTimeStep*model->NofNodes + T[k]];
152
NF[k] += t*velo[(CurrentTimeStep+1)*model->NofNodes + T[k]];
153
}
154
}
155
156
particles->ParticleData[4]->f[n] = i;
157
return (*elmt->FunctionValue)( NF,u,v,w );
158
}
159
160
particles->ParticleData[4]->f[n] = -1;
161
return 0.0;
162
}
163
164
static void vis_RungeKutta(
165
particle_t *particles,
166
element_model_t *model,
167
int n,
168
double *x,
169
double *y,
170
double *z,
171
double *c,
172
double t,
173
double dt,
174
double *f_x0,
175
double *f_y0,
176
double *f_z0,
177
double *f_c0 )
178
{
179
double k1,k2,k3,k4,dx=*x,dy=*y,dz=*z;
180
181
k1 = k2 = k3 = k4 = 0;
182
183
k1 = dt * vis_particles_interpolate( particles, model, n, f_x0, t, dx, dy, dz );
184
k2 = dt * vis_particles_interpolate( particles, model, n, f_x0, t + dt / 2.0, dx + k1 / 2.0, dy, dz );
185
k3 = dt * vis_particles_interpolate( particles, model, n, f_x0, t + dt / 2.0, dx + k2 / 2.0, dy, dz );
186
k4 = dt * vis_particles_interpolate( particles, model, n, f_x0, t + dt, dx + k3, dy, dz );
187
*x += k1 / 6.0 + k2 / 3.0 + k3 / 3.0 + k4 / 6.0;
188
189
k1 = dt * vis_particles_interpolate( particles, model, n, f_y0, t, dx, dy, dz );
190
k2 = dt * vis_particles_interpolate( particles, model, n, f_y0, t + dt / 2.0, dx, dy + k1 / 2.0, dz );
191
k3 = dt * vis_particles_interpolate( particles, model, n, f_y0, t + dt / 2.0, dx, dy + k2 / 2.0, dz );
192
k4 = dt * vis_particles_interpolate( particles, model, n, f_y0, t + dt, dx, dy + k3, dz );
193
*y += k1 / 6.0 + k2 / 3.0 + k3 / 3.0 + k4 / 6.0;
194
195
k1 = dt * vis_particles_interpolate( particles, model, n, f_z0, t, dx, dy, dz );
196
k2 = dt * vis_particles_interpolate( particles, model, n, f_z0, t + dt / 2.0, dx, dy, dz + k1 / 2.0 );
197
k3 = dt * vis_particles_interpolate( particles, model, n, f_z0, t + dt / 2.0, dx, dy, dz + k2 / 2.0 );
198
k4 = dt * vis_particles_interpolate( particles, model, n, f_z0, t + dt, dx, dy, dz + k3 );
199
200
*z += k1 / 6.0 + k2 / 3.0 + k3 / 3.0 + k4 / 6.0;
201
202
if ( f_c0 )
203
{
204
*c = vis_particles_interpolate( particles, model, n, f_c0, t, *x, *y, *z );
205
}
206
}
207
208
static void vis_Euler(
209
particle_t *particles,
210
element_model_t *model,
211
int n,
212
double *x,
213
double *y,
214
double *z,
215
double *c,
216
double t,
217
double dt,
218
double *f_x0,
219
double *f_y0,
220
double *f_z0,
221
double *f_c0 )
222
{
223
double dx=*x,dy=*y,dz=*z;
224
225
*x += dt * vis_particles_interpolate( particles, model, n, f_x0, t, dx, dy, dz );
226
*y += dt * vis_particles_interpolate( particles, model, n, f_y0, t, dx, dy, dz );
227
*z += dt * vis_particles_interpolate( particles, model, n, f_z0, t, dx, dy, dz );
228
229
if ( f_c0 )
230
{
231
*c = vis_particles_interpolate( particles, model, n, f_c0, t, *x, *y, *z );
232
}
233
}
234
235
extern double xmin,xmax,ymin,ymax,zmin,zmax;
236
237
int vis_particle( geometry_t *geometry, element_model_t *model, particle_t *particles, double gtime )
238
{
239
double *f_x0 = NULL, *f_y0 = NULL, *f_z0 = NULL, *f_c0 = NULL;
240
double *PartX, *PartY, *PartZ, *PartC, *PartI;
241
242
double x, y, z, c, CAdd = 0.0, CScl = 1.0;
243
244
double LX,LY,LZ, LC;
245
double r = 0.05, *C;
246
247
double x0,y0,x1,y1,z0,z1;
248
double k1,k2,k3,k4;
249
250
double t, dt, ddt;
251
252
double CEPS = particles->Tolerance;
253
254
int i, j, k, n, quick;
255
256
double s = MAX(MAX(xmax-xmin,ymax-ymin),zmax-zmin);
257
258
float pnt[3], vec[3];
259
260
void gra_set_material(), gra_set_colormap(), gra_sphere_quality(), gra_arrow(), gra_sphere();
261
262
if ( !GlobalOptions.StereoMode )
263
if ( particles->Material->Diffuse[3] < 1.0 )
264
{
265
if ( GlobalPass != 0 ) return TRUE;
266
} else if ( GlobalPass == 0 )
267
{
268
return TRUE;
269
}
270
271
if ( particles->NofParticles < 1 ) return TRUE;
272
if ( !particles->VectorData || !particles->VectorData[0]->f ) return TRUE;
273
if ( !particles->ParticleData || !particles->ParticleData[0]->f ) return TRUE;
274
275
f_x0 = particles->VectorData[0]->f;
276
f_y0 = particles->VectorData[1]->f;
277
f_z0 = particles->VectorData[2]->f;
278
279
gra_set_material( particles->Material );
280
281
if ( particles->ColorData && particles->ColorData->f )
282
{
283
f_c0 = particles->ColorData->f;
284
285
CAdd = particles->ColorData->min;
286
if ( particles->ColorData->max - particles->ColorData->min != 0.0 )
287
CScl = 1.0 / ( particles->ColorData->max - particles->ColorData->min );
288
else
289
CScl = 1.0;
290
291
gra_set_colormap( particles->ColorMap );
292
} else gra_set_colormap( NULL );
293
294
PartX = particles->ParticleData[0]->f;
295
PartY = particles->ParticleData[1]->f;
296
PartZ = particles->ParticleData[2]->f;
297
PartC = particles->ParticleData[3]->f;
298
PartI = particles->ParticleData[4]->f;
299
300
n = particles->NofParticles;
301
if ( particles->SaveNofParticles != n )
302
{
303
{
304
VARIABLE *var = var_new( "_particle_last", TYPE_DOUBLE,5,n );
305
306
particles->X = &M(var,0,0);
307
particles->Y = &M(var,1,0);
308
particles->Z = &M(var,2,0);
309
particles->C = &M(var,3,0);
310
particles->I = &M(var,4,0);
311
}
312
313
for( i=0; i<n; i++ )
314
{
315
particles->X[i] = PartX[i];
316
particles->Y[i] = PartY[i];
317
particles->Z[i] = PartZ[i];
318
particles->C[i] = PartC[i];
319
particles->I[i] = PartI[i];
320
}
321
particles->SaveNofParticles = n;
322
}
323
324
quick = (particles->LineStyle == line_style_line);
325
quick |= epMouseDown && epMouseDownTakesTooLong;
326
327
if ( quick )
328
{
329
if ( particles->Style == particle_style_vector )
330
{
331
gra_beg_lines();
332
} else
333
{
334
gra_polygon_mode( GRA_LINE );
335
}
336
gra_sphere_quality( 1 );
337
338
if ( !(epMouseDown && epMouseDownTakesTooLong) )
339
gra_line_width( particles->LineWidth );
340
else
341
gra_line_width( 1.0 );
342
}
343
344
if ( !quick && (particles->LineStyle == line_style_cylinder) )
345
{
346
gra_sphere_quality( particles->LineQuality );
347
}
348
349
t = 0.0;
350
for( i=0; i<n; i++ )
351
{
352
if ( particles->ParticleData[4]->f[i]<0 ) continue;
353
354
x = PartX[i];
355
y = PartY[i];
356
z = PartZ[i];
357
c = PartC[i];
358
359
if ( particles->Advance && !epMouseDown )
360
{
361
particles->X[i] = x;
362
particles->Y[i] = y;
363
particles->Z[i] = z;
364
particles->C[i] = c;
365
particles->I[i] = PartI[i];
366
367
t = 0.0;
368
while( t < particles->OutDT-CEPS )
369
{
370
dt = MIN( particles->OutDT-t,particles->MaxDT );
371
while( TRUE )
372
{
373
if ( dt < 1.0E-9 ) break;
374
375
x0 = x1 = x;
376
y0 = y1 = y;
377
z0 = z1 = z;
378
379
switch( particles->IntegMethod )
380
{
381
case particle_integ_euler:
382
vis_Euler( particles, model, i, &x0, &y0, &z0, &c, t, dt, f_x0, f_y0, f_z0, f_c0 );
383
if ( particles->IntegPolicy==particle_policy_adaptive )
384
{
385
vis_Euler( particles, model, i, &x1, &y1, &z1, &c, t, dt / 2, f_x0, f_y0, f_z0, f_c0 );
386
vis_Euler( particles, model, i, &x1, &y1, &z1, &c, t + dt / 2, dt / 2, f_x0, f_y0, f_z0, f_c0 );
387
}
388
break;
389
390
case particle_integ_runge_kutta:
391
vis_RungeKutta( particles, model, i, &x0, &y0, &z0, &c, t, dt, f_x0, f_y0, f_z0, f_c0 );
392
if ( particles->IntegPolicy==particle_policy_adaptive )
393
{
394
vis_RungeKutta( particles, model, i, &x1, &y1, &z1, &c, t, dt / 2, f_x0, f_y0, f_z0, f_c0 );
395
vis_RungeKutta( particles, model, i, &x1, &y1, &z1, &c, t + dt / 2, dt / 2, f_x0, f_y0, f_z0, f_c0 );
396
}
397
break;
398
}
399
400
if ( particles->IntegPolicy == particle_policy_fixed )
401
{
402
x1 = x0;
403
y1 = y0;
404
z1 = z0;
405
break;
406
}
407
408
if ( ABS(x0-x1) < CEPS && ABS(y0-y1) < CEPS && ABS(z0-z1) < CEPS ) break;
409
410
dt /= 2;
411
412
if ( BreakLoop ) break;
413
}
414
if ( BreakLoop ) break;
415
416
t += dt;
417
x = x1;
418
y = y1;
419
z = z1;
420
421
if ( dt < 1.0E-9 )
422
{
423
fprintf( stderr, "For Your record: stepping didn't succeed.\n" );
424
break;
425
}
426
if ( BreakLoop ) break;
427
}
428
if ( BreakLoop ) break;
429
430
PartX[i] = x;
431
PartY[i] = y;
432
PartZ[i] = z;
433
PartC[i] = c;
434
}
435
if ( BreakLoop ) break;
436
437
if ( particles->Style == particle_style_vector )
438
{
439
LX = particles->X[i];
440
LY = particles->Y[i];
441
LZ = particles->Z[i];
442
LC = particles->C[i];
443
444
LX = ( 2.0*(LX-xmin) - (xmax-xmin) ) / s;
445
LY = ( 2.0*(LY-ymin) - (ymax-ymin) ) / s;
446
LZ = ( 2.0*(LZ-zmin) - (zmax-zmin) ) / s;
447
448
x = ( 2.0*(x-xmin) - (xmax-xmin) ) / s;
449
y = ( 2.0*(y-ymin) - (ymax-ymin) ) / s;
450
z = ( 2.0*(z-zmin) - (zmax-zmin) ) / s;
451
452
#if 0
453
if ( i==185 )
454
{
455
extern double viewx,viewy,viewz,tox,toy,toz,upx,upy,upz;
456
viewx=LX;
457
viewy=LY;
458
viewz=LZ;
459
tox=x;
460
toy=y;
461
toz=z;
462
upx=0;
463
if ( ABS(LX-x)>ABS(LY-y) || ABS(LZ-z)>ABS(LY-y) ) { upy=1; upz=0; }
464
else { upy=0; upz=1; }
465
continue;
466
}
467
if ( (i%10) ) continue;
468
#endif
469
470
471
pnt[0] = LX;
472
pnt[1] = LY;
473
pnt[2] = LZ;
474
475
vec[0] = x - LX;
476
vec[1] = y - LY;
477
vec[2] = z - LZ;
478
479
r = sqrt( vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] );
480
gra_arrow( pnt,vec,CScl*(c-CAdd),particles->LineStyle,
481
particles->ArrowStyle,0.1*particles->LineWidth*r );
482
} else {
483
x = ( 2.0*(x-xmin) - (xmax-xmin) ) / s;
484
y = ( 2.0*(y-ymin) - (ymax-ymin) ) / s;
485
z = ( 2.0*(z-zmin) - (zmax-zmin) ) / s;
486
c = CScl*(c-CAdd);
487
gra_sphere( x,y,z,c,particles->LineWidth*r*c );
488
}
489
490
if ( epMouseDown && ( i & 30 ) )
491
{
492
if ( RealTime() - gtime > TooLong2 )
493
if ( ++epMouseDownTakesTooLong > 3 )
494
{
495
if ( quick )
496
if ( particles->Style == particle_style_vector )
497
{
498
gra_end_lines( );
499
} else
500
{
501
gra_polygon_mode( GRA_FILL );
502
}
503
return FALSE;
504
} else gtime = RealTime();
505
}
506
}
507
508
particles->Advance = FALSE;
509
510
if ( quick )
511
if ( particles->Style == particle_style_vector )
512
{
513
gra_end_lines( );
514
} else
515
{
516
gra_polygon_mode( GRA_FILL );
517
}
518
519
return TRUE;
520
}
521
522
523
/*******************************************************************************
524
*
525
* Name: vis_particle_alloc
526
*
527
* Purpose: allocate memory for particle_t structure
528
*
529
* Parameters:
530
*
531
* Input: none
532
*
533
* Output: none
534
*
535
* Return value: pointer to allocated memory
536
*
537
******************************************************************************/
538
static particle_t *vis_particle_alloc()
539
{
540
particle_t *particle = (particle_t *)calloc(sizeof(particle_t),1);
541
542
if ( !particle )
543
{
544
fprintf( stderr, "vis_particle_alloc: FATAL: can't alloc a few bytes of memory\n" );
545
}
546
547
return particle;
548
}
549
550
/*******************************************************************************
551
*
552
* Name: vis_particle_delete
553
*
554
* Purpose: free memory associated with particle_t structure
555
*
556
* Parameters:
557
*
558
* Input: (particle_t *) pointer to structure
559
*
560
* Output: none
561
*
562
* Return value: void
563
*
564
******************************************************************************/
565
static void vis_particle_delete(particle_t *particle)
566
{
567
if ( particle ) free( particle );
568
}
569
570
/*******************************************************************************
571
*
572
* Name: vis_initialize_particle_visual
573
*
574
* Purpose: Register particle visual type
575
*
576
* Parameters:
577
*
578
* Input: none
579
*
580
* Output: none
581
*
582
* Return value: vis_add_visual_type (malloc success probably)...
583
*
584
******************************************************************************/
585
int vis_initialize_particle_visual()
586
{
587
static char *visual_name = "Particles";
588
589
visual_type_t VisualDef;
590
591
static particle_t particle;
592
593
static visual_param_t ParticleParams[] =
594
{
595
{ "VectorData1", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
596
{ "VectorData2", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
597
{ "VectorData3", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
598
{ "ParticleDataX", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
599
{ "ParticleDataY", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
600
{ "ParticleDataZ", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
601
{ "ParticleDataC", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
602
{ "ParticleDataI", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
603
{ "ColorData", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, NULL },
604
{ "Material", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, &DefaultMaterial },
605
{ "ColorMap", "%s", 0, VIS_VISUAL_PARAM_POINTER, 0, 0.0, &DefaultColorMap },
606
{ "LineQuality", "%d", 0, VIS_VISUAL_PARAM_INT, 1, 0.0, NULL },
607
{ "LineStyle", "%d", 0, VIS_VISUAL_PARAM_INT, line_style_line, 0.0, NULL },
608
{ "LineWidth", "%lf", 0, VIS_VISUAL_PARAM_FLOAT, 0, 1.0, NULL },
609
{ "ArrowStyle", "%d", 0, VIS_VISUAL_PARAM_INT, arrow_style_stick, 0.0, NULL },
610
{ "OutDT", "%lf", 0, VIS_VISUAL_PARAM_FLOAT, 0, 1.0E-1, NULL },
611
{ "MaxDT", "%lf", 0, VIS_VISUAL_PARAM_FLOAT, 0, 1.0E-3, NULL },
612
{ "Tolerance", "%lf", 0, VIS_VISUAL_PARAM_FLOAT, 0, 1.0E-5, NULL },
613
{ "NofParticles", "%d", 0, VIS_VISUAL_PARAM_INT, 0, 0.0, NULL },
614
{ "Advance", "%d", 0, VIS_VISUAL_PARAM_INT, TRUE, 0.0, NULL },
615
{ "IntegMethod", "%d", 0, VIS_VISUAL_PARAM_INT, particle_integ_runge_kutta, 0.0, NULL },
616
{ "IntegPolicy", "%d", 0, VIS_VISUAL_PARAM_INT, particle_policy_adaptive, 0.0, NULL },
617
{ "Style", "%d", 0, VIS_VISUAL_PARAM_INT, particle_style_vector, 0.0, NULL },
618
{ NULL, NULL, 0, 0, 0,0.0, NULL }
619
};
620
621
int n = 0;
622
623
ParticleParams[n++].Offset = (char *)&particle.VectorData[0] - (char *)&particle;
624
ParticleParams[n++].Offset = (char *)&particle.VectorData[1] - (char *)&particle;
625
ParticleParams[n++].Offset = (char *)&particle.VectorData[2] - (char *)&particle;
626
ParticleParams[n++].Offset = (char *)&particle.ParticleData[0] - (char *)&particle;
627
ParticleParams[n++].Offset = (char *)&particle.ParticleData[1] - (char *)&particle;
628
ParticleParams[n++].Offset = (char *)&particle.ParticleData[2] - (char *)&particle;
629
ParticleParams[n++].Offset = (char *)&particle.ParticleData[3] - (char *)&particle;
630
ParticleParams[n++].Offset = (char *)&particle.ParticleData[4] - (char *)&particle;
631
ParticleParams[n++].Offset = (char *)&particle.ColorData - (char *)&particle;
632
ParticleParams[n++].Offset = (char *)&particle.Material - (char *)&particle;
633
ParticleParams[n++].Offset = (char *)&particle.ColorMap - (char *)&particle;
634
ParticleParams[n++].Offset = (char *)&particle.LineQuality - (char *)&particle;
635
ParticleParams[n++].Offset = (char *)&particle.LineStyle - (char *)&particle;
636
ParticleParams[n++].Offset = (char *)&particle.LineWidth - (char *)&particle;
637
ParticleParams[n++].Offset = (char *)&particle.ArrowStyle - (char *)&particle;
638
ParticleParams[n++].Offset = (char *)&particle.OutDT - (char *)&particle;
639
ParticleParams[n++].Offset = (char *)&particle.MaxDT - (char *)&particle;
640
ParticleParams[n++].Offset = (char *)&particle.Tolerance - (char *)&particle;
641
ParticleParams[n++].Offset = (char *)&particle.NofParticles - (char *)&particle;
642
ParticleParams[n++].Offset = (char *)&particle.Advance - (char *)&particle;
643
ParticleParams[n++].Offset = (char *)&particle.IntegMethod - (char *)&particle;
644
ParticleParams[n++].Offset = (char *)&particle.IntegPolicy - (char *)&particle;
645
ParticleParams[n++].Offset = (char *)&particle.Style - (char *)&particle;
646
647
VisualDef.VisualName = visual_name;
648
VisualDef.RealizeVisual = (int (*)()) vis_particle;
649
VisualDef.AllocParams = (void *(*)()) vis_particle_alloc;
650
VisualDef.DeleteParams = (void (*)()) vis_particle_delete;
651
VisualDef.VisualParams = ParticleParams;
652
653
return vis_add_visual_type( &VisualDef );
654
}
655
656