Statistiques
| Révision :

root / src / lsm_lib.h @ 4

Historique | Voir | Annoter | Télécharger (15,99 ko)

1
/*     
2
       Copyright 2016 ENS de Lyon
3

4
       File author(s):
5
           Typhaine Moreau, Annamaria Kiss <annamaria.kiss@ens-lyon.fr.fr>
6

7
       See accompanying file LICENSE.txt
8
*/
9

    
10
#include <iostream>
11
#include <math.h>
12
#include <sstream>
13
#include <vector>
14
#include <fstream>
15
#include <algorithm>
16

    
17
#include "CImg.h"
18

    
19
using namespace cimg_library;
20
using namespace std;
21

    
22

    
23
//**************************************** GLOBAL IMAGE *************************************************************************
24

    
25
//Invert the image
26
//----------------------------------------------------------------------------
27
CImg<unsigned char> invert_image(CImg<unsigned char> const & img)
28
{
29
  CImg<unsigned char> unity(img._width,img._height,img._depth,1,1);
30
  CImg<unsigned char> inverted = unity - img;
31
  return inverted;
32
}
33

    
34
//Add black slices on each side of the image
35
//----------------------------------------------------------------------------
36
CImg<float> add_side_slices(CImg<float> const & img, int side)
37
{
38
  int s=side*2;
39
  CImg<float> newImg(img._width+s,img._height+s,img._depth+s,1,1);
40

    
41
  cimg_forXYZ(img,x,y,z)
42
    {
43
      newImg(x+side,y+side,z+side)=img(x,y,z);   
44
    }
45
  return newImg;
46
}
47

    
48
//Remove slices
49
//----------------------------------------------------------------------------
50
CImg<float> remove_side_slices(CImg<float> const & img, int side)
51
{
52
  int s=side*2;
53
  CImg<float> newImg(img._width-s,img._height-s,img._depth-s,1,0);
54

    
55
  cimg_forXYZ(newImg,x,y,z)
56
    {
57
      newImg(x,y,z)=img(x+side,y+side,z+side);   
58
    }
59
  return newImg;
60
}
61

    
62
//Threshold linear along Z   1:background  0:cells
63
//----------------------------------------------------------------------------
64
CImg<unsigned char> threshold_linear_alongZ(CImg<float> const & img, int t1, int t2)
65
{
66
  CImg<unsigned char> outside(img._width,img._height,img._depth,1,0);
67
  for(int z=0; z<img._depth ; z++)
68
    {
69
      cimg_forXY(outside,x,y)
70
        {
71
          float thresh = t1 + (t2-t1)*(z*1.0/img._depth);
72
          if(img(x,y,z)<thresh)
73
            {outside(x,y,z)=1;}        
74
        }
75
    }
76
  outside.label();
77
  cimg_forXYZ(outside,x,y,z)
78
    {
79
      if(outside(x,y,z)>0) {outside(x,y,z)=0;}
80
      else {outside(x,y,z)=1;}
81
    }
82
  return outside;
83
}
84

    
85
//LSM contour init +c0 background, -c0 cells
86
//--------------------------------------------------------------------------
87
CImg<float> lsm_contour_init(CImg<unsigned char> const & region,int c0)
88
{
89
  CImg<float> initLSM(region._width,region._height,region._depth,1,c0);
90
  initLSM=initLSM-2*c0*region;
91
  return initLSM;
92
}
93

    
94
//Gradient 3D with central finite differences
95
//----------------------------------------------------------------------------
96
CImgList<float> gradient(CImg<float> const & img)
97
{
98
  //List of 3 images the same size as img
99
  CImgList<float> grad(3,img._width,img._height,img._depth,1,0);
100

    
101
  //Image loop with a 3*3*3 neighborhood
102
  CImg_3x3x3(I,float);
103
  cimg_for3x3x3(img,x,y,z,0,I,float)
104
    {
105
      grad(0,x,y,z) = (Incc - Ipcc)/2; //grad x = (img(x+1,y,z)-img(x-1,y,z))/2
106
      grad(1,x,y,z) = (Icnc - Icpc)/2; //grad y
107
      grad(2,x,y,z) = (Iccn - Iccp)/2; //grad z
108
    }
109
  return grad;
110
}
111

    
112
//Norm of the gradient
113
//---------------------------------------------------------------------------
114
CImg<float> gradient_norm(CImg<float> const & img)
115
{
116
  CImgList<float> grad = gradient(img);
117
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
118
  float f=0;
119
  cimg_forXYZ(res,x,y,z)
120
    {
121
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
122
      res(x,y,z)=sqrt(f);
123
    }
124
  return res;
125
}
126

    
127

    
128
//Edge indicator
129
//---------------------------------------------------------------------------
130
CImg<float> edge_indicator(CImgList<float> const & grad)
131
{
132
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
133
  float f=0;
134
  cimg_forXYZ(res,x,y,z)
135
    {
136
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
137
      res(x,y,z)=1.0/(1.0+f);
138
      //res(x,y,z)=exp(-f);
139
    }
140
  return res;
141
}
142

    
143
//Edge indicator 1 (gradient)
144
//---------------------------------------------------------------------------
145
CImg<float> edge_indicator1(CImg<float> const & img)
146
{
147
  CImgList<float> grad;
148
  grad = gradient(img);
149
  CImg<float> res(img._width,img._height,img._depth,1,0);
150
  float f=0;
151
  cimg_forXYZ(res,x,y,z)
152
    {
153
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
154
      res(x,y,z)=1.0/(1.0+f);
155
    }
156
  return res;
157
}
158

    
159
CImg<float> edge_indicator1(CImg<float> const & img, float gamma)
160
{
161
  CImgList<float> grad;
162
  grad = gradient(img);
163
  CImg<float> res(img._width,img._height,img._depth,1,0);
164
  float f=0;
165
  cimg_forXYZ(res,x,y,z)
166
    {
167
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
168
      res(x,y,z)=1.0/(1.0+f/gamma/gamma);
169
    }
170
  return res;
171
}
172

    
173
//Edge indicator 2 (hessienne, computed without smoothing)
174
//---------------------------------------------------------------------------
175
CImg<float> edge_indicator2(CImg<float> const & img)
176
{
177
  CImg<float> res(img._width,img._height,img._depth,1,0); 
178
  float f=0;
179
  cimg_forXYZ(res,x,y,z)
180
    {
181
    int xp=x-1;
182
        if (x==0){xp=x;}
183
        int xn=x+1;
184
        if (x==img._width-1){xn=x;}
185
        int yp=y-1;
186
        if (y==0){yp=y;}
187
        int yn=y+1;
188
        if (y==img._height-1){yn=y;}
189
        int zp=z-1;
190
        if (z==0){zp=z;}
191
        int zn=z+1;
192
        if (z==img._depth-1){zn=z;}
193

    
194
        CImg<float> hess(3,3,1,1,0);
195
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
196
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
197
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
198
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
199
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
200
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
201
        
202
        //val : 3 eigen values as an array, decreasing order
203
        //vec : 3 eigen vectors as a 3*3 image
204
        //have to be double or create NaN
205
        CImg<double> val,vec;
206
        hess.symmetric_eigen(val,vec);
207
        if (val[2]>0) val[2]=0;
208
        val[2]=-val[2];
209
        //res(x,y,z)=1.0/(1.0 +val[2]*(50/3.));  //h=g test4
210
    //res(x,y,z)=1.0/(1.0 +val[2]*val[2]*(50/3.)*(50/3.) );
211
    //res(x,y,z)=1.0/(1.0 +exp(-val[2]));
212
    //res(x,y,z)=exp(-val[2]);
213
    //res(x,y,z)=exp(-val[2]*val[2]);
214
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]);
215
    }
216
  return res;
217
}
218

    
219
//Edge indicator 2 (hessienne, computed with smoothing)
220
//---------------------------------------------------------------------------
221
CImg<float> edge_indicator2s(CImg<float> const & img, float gamma)
222
{
223
  CImg<float> res(img._width,img._height,img._depth,1,0);
224
    
225
  // make a minimal blur before taking derivatives
226
  CImg<float> imgBlur=img.get_blur(2);
227
  
228
  float f=0;
229
  cimg_forXYZ(res,x,y,z)
230
    {
231
    int xp=x-1;
232
        if (x==0){xp=x;}
233
        int xn=x+1;
234
        if (x==img._width-1){xn=x;}
235
        int yp=y-1;
236
        if (y==0){yp=y;}
237
        int yn=y+1;
238
        if (y==img._height-1){yn=y;}
239
        int zp=z-1;
240
        if (z==0){zp=z;}
241
        int zn=z+1;
242
        if (z==img._depth-1){zn=z;}
243

    
244
        CImg<float> hess(3,3,1,1,0);
245
        hess(0,0) = imgBlur(xp,y,z) + imgBlur(xn,y,z) - 2*imgBlur(x,y,z);          // Hxx
246
        hess(1,1) = imgBlur(x,yp,z) + imgBlur(x,yn,z) - 2*imgBlur(x,y,z);          // Hyy
247
        hess(2,2) = imgBlur(x,y,zp) + imgBlur(x,y,zn) - 2*imgBlur(x,y,z);          // Hzz
248
        hess(1,0) = hess(0,1) = (imgBlur(xp,yp,z) + imgBlur(xn,yn,z) - imgBlur(xp,yn,z) - imgBlur(xn,yp,z))/4; // Hxy = Hyx
249
        hess(2,0) = hess(0,2) = (imgBlur(xp,y,zp) + imgBlur(xn,y,zn) - imgBlur(xp,y,zn) - imgBlur(xn,y,zp))/4; // Hxz = Hzx
250
        hess(2,1) = hess(1,2) = (imgBlur(x,yp,zp) + imgBlur(x,yn,zn) - imgBlur(x,yp,zn) - imgBlur(x,yn,zp))/4; // Hyz = Hzy
251
        
252
        //val : 3 eigen values as an array, decreasing order
253
        //vec : 3 eigen vectors as a 3*3 image
254
        //have to be double or create NaN
255
        CImg<double> val,vec;
256
        hess.symmetric_eigen(val,vec);
257
        if (val[2]>0) val[2]=0;
258
        val[2]=-val[2];
259
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
260
    }
261
  return res;
262
}
263

    
264

    
265
CImg<float> edge_indicator2(CImg<float> const & img, float gamma)
266
{
267
  CImg<float> res(img._width,img._height,img._depth,1,0);
268
  float f=0;
269
  cimg_forXYZ(res,x,y,z)
270
    {
271
    int xp=x-1;
272
        if (x==0){xp=x;}
273
        int xn=x+1;
274
        if (x==img._width-1){xn=x;}
275
        int yp=y-1;
276
        if (y==0){yp=y;}
277
        int yn=y+1;
278
        if (y==img._height-1){yn=y;}
279
        int zp=z-1;
280
        if (z==0){zp=z;}
281
        int zn=z+1;
282
        if (z==img._depth-1){zn=z;}
283

    
284
        CImg<float> hess(3,3,1,1,0);
285
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
286
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
287
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
288
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
289
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
290
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
291
        
292
        //val : 3 eigen values as an array, decreasing order
293
        //vec : 3 eigen vectors as a 3*3 image
294
        //have to be double or create NaN
295
        CImg<double> val,vec;
296
        hess.symmetric_eigen(val,vec);
297
        if (val[2]>0) val[2]=0;
298
        //val[2]=-val[2];
299
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
300
    }
301
  return res;
302
}
303

    
304
//Edge indicator 3 (image based)
305
//---------------------------------------------------------------------------
306
CImg<float> edge_indicator3(CImg<float> const & img)
307
{
308
  CImg<float> res(img._width,img._height,img._depth,1,0);
309
  cimg_forXYZ(res,x,y,z)
310
    {
311
      res(x,y,z)=1.0/(1.0+img(x,y,z)*img(x,y,z));
312
    }
313
  return res;
314
}
315

    
316
CImg<float> edge_indicator3(CImg<float> const & img, float gamma)
317
{
318
  CImg<float> res(img._width,img._height,img._depth,1,0);
319
  cimg_forXYZ(res,x,y,z)
320
    {
321
                res(x,y,z)=1.0/(1.0+(img(x,y,z)/gamma)*(img(x,y,z)/gamma));
322
    }
323
  return res;
324
}
325

    
326
//Edge image (based on lambda3 of the hessien)
327
//---------------------------------------------------------------------------
328
CImg<float> edge_lambda3(CImg<float> const & img)
329
{
330
  CImg<float> res(img._width,img._height,img._depth,1,0);
331
  float f=0;
332
  cimg_forXYZ(res,x,y,z)
333
    {
334
    int xp=x-1;
335
        if (x==0){xp=x;}
336
        int xn=x+1;
337
        if (x==img._width-1){xn=x;}
338
        int yp=y-1;
339
        if (y==0){yp=y;}
340
        int yn=y+1;
341
        if (y==img._height-1){yn=y;}
342
        int zp=z-1;
343
        if (z==0){zp=z;}
344
        int zn=z+1;
345
        if (z==img._depth-1){zn=z;}
346

    
347
        CImg<float> hess(3,3,1,1,0);
348
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
349
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
350
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
351
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
352
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
353
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
354
        
355
        //val : 3 eigen values as an array, decreasing order
356
        //vec : 3 eigen vectors as a 3*3 image
357
        //have to be double or create NaN
358
        CImg<double> val,vec;
359
        hess.symmetric_eigen(val,vec);
360
        if (val[2]>0) val[2]=0;
361
    res(x,y,z)=-val[2];
362
    }
363
  return res;
364
}
365

    
366

    
367
//Wall indicator
368
//---------------------------------------------------------------------------
369
CImg<float> wall_indicator(CImg<float> const & img)
370
{
371
  CImg<float> res(img._width,img._height,img._depth,1,0);
372
  cimg_forXYZ(res,x,y,z)
373
    {
374
      res(x,y,z)=1.0/(1.0+(img(x,y,z)*img(x,y,z)));
375
    }
376
  return res;
377
}
378

    
379
//Dirac function
380
//-------------------------------------------------------------------------
381
CImg<float> Dirac(CImg<float> const & img, float sigma)
382
{
383
  CImg<float> fImg(img._width,img._height,img._depth,1,0);
384
  float f=0;
385
  cimg_forXYZ(img,x,y,z)
386
    {
387
      if(abs(img(x,y,z))<=sigma)
388
        {
389
          f=(1.0/(2*sigma))*(1+cos(M_PI*img(x,y,z)/sigma));
390
        }
391
      else {f=0;}
392
      fImg(x,y,z)=f;
393
    }
394
  return fImg;
395
} 
396

    
397
//Normal vector
398
//------------------------------------------------------------------------
399
CImgList<float> normal_vector(CImg<float> const & img)
400
{
401
  CImgList<float> normal_vector(3,img._width,img._height,img._depth,1,0); 
402

    
403
  CImg_3x3x3(I,float);        
404
  cimg_for3x3x3(img,x,y,z,0,I,float) 
405
    {
406
      float nx = (Incc-Ipcc)/2.0;    
407
      float ny = (Icnc-Icpc)/2.0;   
408
      float nz = (Iccn-Iccp)/2.0;
409
      //border
410
      if((x==0)or(y==0)or(z==0))
411
        {nx=ny=nz=0;}
412
      if((x==img.width()-1)or(y==img.height()-1)or(z==img.depth()-1))
413
        {nx=ny=nz=0;}
414

    
415
      float norm=1;
416
      if((nx!=0)or(ny!=0)or(nz!=0))
417
        {norm = sqrt(nx*nx+ny*ny+nz*nz);}
418
 
419
      normal_vector(0,x,y,z)=nx/norm;
420
      normal_vector(1,x,y,z)=ny/norm;
421
      normal_vector(2,x,y,z)=nz/norm;
422
    }
423
  return normal_vector;
424
}
425

    
426

    
427
//Curvature
428
//------------------------------------------------------------------------
429
CImg<float> curvature2(CImgList<float> const & N)
430
{
431
  CImg<float> K(N[0]._width,N[0]._height,N[0]._depth,1,0);
432
  cimg_forXYZ(N[0],x,y,z)
433
    {
434
      float kx=0;
435
      float ky=0;
436
      float kz=0;
437
      if(x==0)
438
        {kx=N[0](x+1,y,z)-N[0](x,y,z);}
439
      else if(x==N[0]._width-1)
440
        {kx=N[0](x,y,z)-N[0](x-1,y,z);}
441
      else
442
        {kx=(N[0](x+1,y,z)-N[0](x-1,y,z))/2.0;}
443

    
444
     if(y==0)
445
        {ky=N[1](x,y+1,z)-N[1](x,y,z);}
446
      else if(y==N[1]._height-1)
447
        {ky=N[1](x,y,z)-N[1](x,y-1,z);}
448
      else
449
        {ky=(N[1](x,y+1,z)-N[1](x,y-1,z))/2.0;}
450

    
451
     if(z==0)
452
        {kz=N[2](x,y,z+1)-N[2](x,y,z);}
453
      else if(z==N[2]._depth-1)
454
        {kz=N[2](x,y,z)-N[2](x,y,z-1);}
455
      else
456
        {kz=(N[2](x,y,z+1)-N[2](x,y,z-1))/2.0;}
457

    
458
     K(x,y,z)=kx+ky+kz;
459
    }
460
  return K;
461
}
462

    
463
// Compute image laplacian
464
//--------------------------------------------------------------------
465
CImg<float> laplacian(CImg<float> const & img)
466
{
467
  CImg<float> laplacian(img._width,img._height,img._depth,1,0);
468
  CImg_3x3x3(I,float);
469
  cimg_for3x3x3(img,x,y,z,0,I,float)
470
    {
471
      laplacian(x,y,z) =Incc+Ipcc+Icnc+Icpc+Iccn+Iccp - 6*Iccc;
472
    }
473
  return laplacian;
474
}
475

    
476
//Evolution AK2 contour
477
//-------------------------------------------------------------------------
478
CImg<float> evolution_AK2_contour(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, float beta, float epsilon, int dt)
479
{
480
  CImg<float> diracU=Dirac(u,epsilon); 
481
  CImgList<float> N=normal_vector(u);
482
  CImg<float> K=curvature2(N);
483
  CImg<float> L=laplacian(u);
484
  float term=0;
485

    
486
  cimg_forXYZ(u,x,y,z)
487
    {
488
      term=0;
489
      if (diracU(x,y,z)!=0)
490
        {
491
          //weighted length term
492
          if(lam!=0)
493
            {term=( gg(0,x,y,z)*N(0,x,y,z) + gg(1,x,y,z)*N(1,x,y,z) + gg(2,x,y,z)*N(2,x,y,z) + (g(x,y,z)*K(x,y,z))) *lam;}
494
          //length term
495
          if(beta!=0)
496
            {term=term + K(x,y,z)*beta;}
497
          //weighted area term
498
          if(alf!=0)
499
            {term=term + h(x,y,z)*alf;}
500
          //regularization
501
          term=term*diracU(x,y,z);
502
          //penalizing term
503
          term=term + (L(x,y,z)-K(x,y,z))*mu;
504
        }
505
      else
506
        {
507
          //penalizing term
508
          term=(L(x,y,z)-K(x,y,z))*mu;
509
        }
510
      
511
      u(x,y,z)=u(x,y,z) + term*dt;
512
    }
513
  return u;
514
}
515

    
516
//Evolution AK2 contour cells
517
//-------------------------------------------------------------------------
518
CImg<float> evolution_AK2_contour_cells(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, int beta, float epsilon, int dt, vector<int> min_list)
519
{
520
  CImg<float> diracU=Dirac(u,epsilon); 
521
  CImgList<float> N=normal_vector(u);
522
  CImg<float> K=curvature2(N);
523
  CImg<float> L=laplacian(u);
524
  float term=0;
525
  int xmax=u._width;
526
  int ymax=u._height;
527
  int zmax=u._depth;
528
  int c0=-4;
529

    
530
  cimg_forXYZ(u,x,y,z)
531
    {
532
      int xb=x+min_list[0];
533
      int yb=y+min_list[1];
534
      int zb=z+min_list[2];
535
      term=0;
536
      if (diracU(x,y,z)!=0)
537
        {
538
          //weighted length term
539
          if(lam!=0)
540
            {term=( gg(0,xb,yb,zb)*N(0,x,y,z) + gg(1,xb,yb,zb)*N(1,x,y,z) + gg(2,xb,yb,zb)*N(2,x,y,z) + (g(xb,yb,zb)*K(x,y,z))) *lam;}
541
          //length term
542
          if(beta!=0)
543
            {term=term + K(x,y,z)*beta;}
544
          //weighted area term
545
          if(alf!=0)
546
            {term=term + h(xb,yb,zb)*alf;}            
547
          //regularization
548
          term=term*diracU(x,y,z);
549
          //penalizing term
550
          term=term + (L(x,y,z)-K(x,y,z))*mu;
551
        }
552
      else
553
        {
554
          //penalizing term
555
          term=(L(x,y,z)-K(x,y,z))*mu;
556
        }
557
      // computing the evolution
558
      u(x,y,z)=u(x,y,z) + term*dt;
559
      // box boundary regularisation
560
      if ((x==0) or (x==xmax) or (x==1) or (x==xmax-1) or(y==0) or (y==ymax)or(y==1) or (y==ymax-1) or (z==0) or (z==zmax)or (z==1) or (z==zmax-1))
561
      {u(x,y,z)=c0;}
562
    }
563
  return u;
564
}