/[escript]/branches/diaplayground/ripley/src/Brick.cpp
ViewVC logotype

Diff of /branches/diaplayground/ripley/src/Brick.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3796 by gross, Thu Feb 2 06:26:15 2012 UTC revision 4154 by jfenwick, Tue Jan 22 09:30:23 2013 UTC
# Line 1  Line 1 
1    
2  /*******************************************************  /*****************************************************************************
3  *  *
4  * Copyright (c) 2003-2012 by University of Queensland  * Copyright (c) 2003-2013 by University of Queensland
5  * Earth Systems Science Computational Center (ESSCC)  * http://www.uq.edu.au
 * http://www.uq.edu.au/esscc  
6  *  *
7  * Primary Business: Queensland, Australia  * Primary Business: Queensland, Australia
8  * Licensed under the Open Software License version 3.0  * Licensed under the Open Software License version 3.0
9  * http://www.opensource.org/licenses/osl-3.0.php  * http://www.opensource.org/licenses/osl-3.0.php
10  *  *
11  *******************************************************/  * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12    * Development since 2012 by School of Earth Sciences
13    *
14    *****************************************************************************/
15    
16  #include <ripley/Brick.h>  #include <ripley/Brick.h>
17  extern "C" {  extern "C" {
18  #include <paso/SystemMatrix.h>  #include <paso/SystemMatrix.h>
19  }  }
20    
21    #ifdef USE_NETCDF
22    #include <netcdfcpp.h>
23    #endif
24    
25  #if USE_SILO  #if USE_SILO
26  #include <silo.h>  #include <silo.h>
27  #ifdef ESYS_MPI  #ifdef ESYS_MPI
# Line 32  namespace ripley { Line 38  namespace ripley {
38  Brick::Brick(int n0, int n1, int n2, double x0, double y0, double z0,  Brick::Brick(int n0, int n1, int n2, double x0, double y0, double z0,
39               double x1, double y1, double z1, int d0, int d1, int d2) :               double x1, double y1, double z1, int d0, int d1, int d2) :
40      RipleyDomain(3),      RipleyDomain(3),
     m_gNE0(n0),  
     m_gNE1(n1),  
     m_gNE2(n2),  
41      m_x0(x0),      m_x0(x0),
42      m_y0(y0),      m_y0(y0),
43      m_z0(z0),      m_z0(z0),
44      m_l0(x1-x0),      m_l0(x1-x0),
45      m_l1(y1-y0),      m_l1(y1-y0),
46      m_l2(z1-z0),      m_l2(z1-z0)
     m_NX(d0),  
     m_NY(d1),  
     m_NZ(d2)  
47  {  {
48        // ignore subdivision parameters for serial run
49        if (m_mpiInfo->size == 1) {
50            d0=1;
51            d1=1;
52            d2=1;
53        }
54    
55        bool warn=false;
56        // if number of subdivisions is non-positive, try to subdivide by the same
57        // ratio as the number of elements
58        if (d0<=0 && d1<=0 && d2<=0) {
59            warn=true;
60            d0=(int)(pow(m_mpiInfo->size*(n0+1)*(n0+1)/((float)(n1+1)*(n2+1)), 1.f/3));
61            d0=max(1, d0);
62            d1=max(1, (int)(d0*n1/(float)n0));
63            d2=m_mpiInfo->size/(d0*d1);
64            if (d0*d1*d2 != m_mpiInfo->size) {
65                // ratios not the same so leave "smallest" side undivided and try
66                // dividing 2 sides only
67                if (n0>=n1) {
68                    if (n1>=n2) {
69                        d0=d1=0;
70                        d2=1;
71                    } else {
72                        d0=d2=0;
73                        d1=1;
74                    }
75                } else {
76                    if (n0>=n2) {
77                        d0=d1=0;
78                        d2=1;
79                    } else {
80                        d0=1;
81                        d1=d2=0;
82                    }
83                }
84            }
85        }
86        if (d0<=0 && d1<=0) {
87            warn=true;
88            d0=max(1, int(sqrt(m_mpiInfo->size*(n0+1)/(float)(n1+1))));
89            d1=m_mpiInfo->size/d0;
90            if (d0*d1*d2 != m_mpiInfo->size) {
91                // ratios not the same so subdivide side with more elements only
92                if (n0>n1) {
93                    d0=0;
94                    d1=1;
95                } else {
96                    d0=1;
97                    d1=0;
98                }
99            }
100        } else if (d0<=0 && d2<=0) {
101            warn=true;
102            d0=max(1, int(sqrt(m_mpiInfo->size*(n0+1)/(float)(n2+1))));
103            d2=m_mpiInfo->size/d0;
104            if (d0*d1*d2 != m_mpiInfo->size) {
105                // ratios not the same so subdivide side with more elements only
106                if (n0>n2) {
107                    d0=0;
108                    d2=1;
109                } else {
110                    d0=1;
111                    d2=0;
112                }
113            }
114        } else if (d1<=0 && d2<=0) {
115            warn=true;
116            d1=max(1, int(sqrt(m_mpiInfo->size*(n1+1)/(float)(n2+1))));
117            d2=m_mpiInfo->size/d1;
118            if (d0*d1*d2 != m_mpiInfo->size) {
119                // ratios not the same so subdivide side with more elements only
120                if (n1>n2) {
121                    d1=0;
122                    d2=1;
123                } else {
124                    d1=1;
125                    d2=0;
126                }
127            }
128        }
129        if (d0<=0) {
130            // d1,d2 are preset, determine d0
131            d0=m_mpiInfo->size/(d1*d2);
132        } else if (d1<=0) {
133            // d0,d2 are preset, determine d1
134            d1=m_mpiInfo->size/(d0*d2);
135        } else if (d2<=0) {
136            // d0,d1 are preset, determine d2
137            d2=m_mpiInfo->size/(d0*d1);
138        }
139    
140        m_NX=d0;
141        m_NY=d1;
142        m_NZ=d2;
143    
144      // ensure number of subdivisions is valid and nodes can be distributed      // ensure number of subdivisions is valid and nodes can be distributed
145      // among number of ranks      // among number of ranks
146      if (m_NX*m_NY*m_NZ != m_mpiInfo->size)      if (m_NX*m_NY*m_NZ != m_mpiInfo->size)
147          throw RipleyException("Invalid number of spatial subdivisions");          throw RipleyException("Invalid number of spatial subdivisions");
148    
149      if ((n0+1)%m_NX > 0 || (n1+1)%m_NY > 0 || (n2+1)%m_NZ > 0)      if (warn) {
150          throw RipleyException("Number of elements+1 must be separable into number of ranks in each dimension");          cout << "Warning: Automatic domain subdivision (d0=" << d0 << ", d1="
151                << d1 << ", d2=" << d2 << "). This may not be optimal!" << endl;
152        }
153    
154        if ((n0+1)%m_NX > 0) {
155            double Dx=m_l0/n0;
156            n0=(int)round((float)(n0+1)/d0+0.5)*d0-1;
157            m_l0=Dx*n0;
158            cout << "Warning: Adjusted number of elements and length. N0="
159                << n0 << ", l0=" << m_l0 << endl;
160        }
161        if ((n1+1)%m_NY > 0) {
162            double Dy=m_l1/n1;
163            n1=(int)round((float)(n1+1)/d1+0.5)*d1-1;
164            m_l1=Dy*n1;
165            cout << "Warning: Adjusted number of elements and length. N1="
166                << n1 << ", l1=" << m_l1 << endl;
167        }
168        if ((n2+1)%m_NZ > 0) {
169            double Dz=m_l2/n2;
170            n2=(int)round((float)(n2+1)/d2+0.5)*d2-1;
171            m_l2=Dz*n2;
172            cout << "Warning: Adjusted number of elements and length. N2="
173                << n2 << ", l2=" << m_l2 << endl;
174        }
175    
176        m_gNE0=n0;
177        m_gNE1=n1;
178        m_gNE2=n2;
179    
180      if ((m_NX > 1 && (n0+1)/m_NX<2) || (m_NY > 1 && (n1+1)/m_NY<2) || (m_NZ > 1 && (n2+1)/m_NZ<2))      if ((m_NX > 1 && (n0+1)/m_NX<2) || (m_NY > 1 && (n1+1)/m_NY<2) || (m_NZ > 1 && (n2+1)/m_NZ<2))
181          throw RipleyException("Too few elements for the number of ranks");          throw RipleyException("Too few elements for the number of ranks");
# Line 121  bool Brick::operator==(const AbstractDom Line 245  bool Brick::operator==(const AbstractDom
245      return false;      return false;
246  }  }
247    
248    void Brick::readBinaryGrid(escript::Data& out, string filename,
249                               const vector<int>& first,
250                               const vector<int>& numValues) const
251    {
252        // check destination function space
253        int myN0, myN1, myN2;
254        if (out.getFunctionSpace().getTypeCode() == Nodes) {
255            myN0 = m_N0;
256            myN1 = m_N1;
257            myN2 = m_N2;
258        } else if (out.getFunctionSpace().getTypeCode() == Elements ||
259                    out.getFunctionSpace().getTypeCode() == ReducedElements) {
260            myN0 = m_NE0;
261            myN1 = m_NE1;
262            myN2 = m_NE2;
263        } else
264            throw RipleyException("readBinaryGrid(): invalid function space for output data object");
265    
266        // check file existence and size
267        ifstream f(filename.c_str(), ifstream::binary);
268        if (f.fail()) {
269            throw RipleyException("readBinaryGrid(): cannot open file");
270        }
271        f.seekg(0, ios::end);
272        const int numComp = out.getDataPointSize();
273        const int filesize = f.tellg();
274        const int reqsize = numValues[0]*numValues[1]*numValues[2]*numComp*sizeof(float);
275        if (filesize < reqsize) {
276            f.close();
277            throw RipleyException("readBinaryGrid(): not enough data in file");
278        }
279    
280        // check if this rank contributes anything
281        if (first[0] >= m_offset0+myN0 || first[0]+numValues[0] <= m_offset0 ||
282                first[1] >= m_offset1+myN1 || first[1]+numValues[1] <= m_offset1 ||
283                first[2] >= m_offset2+myN2 || first[2]+numValues[2] <= m_offset2) {
284            f.close();
285            return;
286        }
287    
288        // now determine how much this rank has to write
289    
290        // first coordinates in data object to write to
291        const int first0 = max(0, first[0]-m_offset0);
292        const int first1 = max(0, first[1]-m_offset1);
293        const int first2 = max(0, first[2]-m_offset2);
294        // indices to first value in file
295        const int idx0 = max(0, m_offset0-first[0]);
296        const int idx1 = max(0, m_offset1-first[1]);
297        const int idx2 = max(0, m_offset2-first[2]);
298        // number of values to write
299        const int num0 = min(numValues[0]-idx0, myN0-first0);
300        const int num1 = min(numValues[1]-idx1, myN1-first1);
301        const int num2 = min(numValues[2]-idx2, myN2-first2);
302    
303        out.requireWrite();
304        vector<float> values(num0*numComp);
305        const int dpp = out.getNumDataPointsPerSample();
306    
307        for (index_t z=0; z<num2; z++) {
308            for (index_t y=0; y<num1; y++) {
309                const int fileofs = numComp*(idx0+(idx1+y)*numValues[0]+(idx2+z)*numValues[0]*numValues[1]);
310                f.seekg(fileofs*sizeof(float));
311                f.read((char*)&values[0], num0*numComp*sizeof(float));
312                const int dataIndex = first0+(first1+y)*myN0+(first2+z)*myN0*myN1;
313    
314                for (index_t x=0; x<num0; x++) {
315                    double* dest = out.getSampleDataRW(dataIndex+x);
316                    for (index_t c=0; c<numComp; c++) {
317                        for (index_t q=0; q<dpp; q++) {
318                            *dest++ = static_cast<double>(values[x*numComp+c]);
319                        }
320                    }
321                }
322            }
323        }
324    
325        f.close();
326    }
327    
328    void Brick::readNcGrid(escript::Data& out, string filename, string varname,
329                const vector<int>& first, const vector<int>& numValues) const
330    {
331    #ifdef USE_NETCDF
332        // check destination function space
333        int myN0, myN1, myN2;
334        if (out.getFunctionSpace().getTypeCode() == Nodes) {
335            myN0 = m_N0;
336            myN1 = m_N1;
337            myN2 = m_N2;
338        } else if (out.getFunctionSpace().getTypeCode() == Elements ||
339                    out.getFunctionSpace().getTypeCode() == ReducedElements) {
340            myN0 = m_NE0;
341            myN1 = m_NE1;
342            myN2 = m_NE2;
343        } else
344            throw RipleyException("readNcGrid(): invalid function space for output data object");
345    
346        if (first.size() != 3)
347            throw RipleyException("readNcGrid(): argument 'first' must have 3 entries");
348    
349        if (numValues.size() != 3)
350            throw RipleyException("readNcGrid(): argument 'numValues' must have 3 entries");
351    
352        // check file existence and size
353        NcFile f(filename.c_str(), NcFile::ReadOnly);
354        if (!f.is_valid())
355            throw RipleyException("readNcGrid(): cannot open file");
356    
357        NcVar* var = f.get_var(varname.c_str());
358        if (!var)
359            throw RipleyException("readNcGrid(): invalid variable name");
360    
361        // TODO: rank>0 data support
362        const int numComp = out.getDataPointSize();
363        if (numComp > 1)
364            throw RipleyException("readNcGrid(): only scalar data supported");
365    
366        const int dims = var->num_dims();
367        const long *edges = var->edges();
368    
369        // is this a slice of the data object (dims!=3)?
370        // note the expected ordering of edges (as in numpy: z,y,x)
371        if ( (dims==3 && (numValues[2] > edges[0] || numValues[1] > edges[1]
372                          || numValues[0] > edges[2]))
373                || (dims==2 && numValues[2]>1)
374                || (dims==1 && (numValues[2]>1 || numValues[1]>1)) ) {
375            throw RipleyException("readNcGrid(): not enough data in file");
376        }
377    
378        // check if this rank contributes anything
379        if (first[0] >= m_offset0+myN0 || first[0]+numValues[0] <= m_offset0 ||
380                first[1] >= m_offset1+myN1 || first[1]+numValues[1] <= m_offset1 ||
381                first[2] >= m_offset2+myN2 || first[2]+numValues[2] <= m_offset2) {
382            return;
383        }
384    
385        // now determine how much this rank has to write
386    
387        // first coordinates in data object to write to
388        const int first0 = max(0, first[0]-m_offset0);
389        const int first1 = max(0, first[1]-m_offset1);
390        const int first2 = max(0, first[2]-m_offset2);
391        // indices to first value in file
392        const int idx0 = max(0, m_offset0-first[0]);
393        const int idx1 = max(0, m_offset1-first[1]);
394        const int idx2 = max(0, m_offset2-first[2]);
395        // number of values to write
396        const int num0 = min(numValues[0]-idx0, myN0-first0);
397        const int num1 = min(numValues[1]-idx1, myN1-first1);
398        const int num2 = min(numValues[2]-idx2, myN2-first2);
399    
400        vector<double> values(num0*num1*num2);
401        if (dims==3) {
402            var->set_cur(idx2, idx1, idx0);
403            var->get(&values[0], num2, num1, num0);
404        } else if (dims==2) {
405            var->set_cur(idx1, idx0);
406            var->get(&values[0], num1, num0);
407        } else {
408            var->set_cur(idx0);
409            var->get(&values[0], num0);
410        }
411    
412        const int dpp = out.getNumDataPointsPerSample();
413        out.requireWrite();
414    
415        for (index_t z=0; z<num2; z++) {
416            for (index_t y=0; y<num1; y++) {
417    #pragma omp parallel for
418                for (index_t x=0; x<num0; x++) {
419                    const int dataIndex = first0+(first1+y)*myN0+(first2+z)*myN0*myN1+x;
420                    const int srcIndex=z*num1*num0+y*num0+x;
421                    double* dest = out.getSampleDataRW(dataIndex);
422                    for (index_t q=0; q<dpp; q++) {
423                        *dest++ = values[srcIndex];
424                    }
425                }
426            }
427        }
428    #else
429        throw RipleyException("readNcGrid(): not compiled with netCDF support");
430    #endif
431    }
432    
433  void Brick::dump(const string& fileName) const  void Brick::dump(const string& fileName) const
434  {  {
435  #if USE_SILO  #if USE_SILO
# Line 528  void Brick::setToSize(escript::Data& out Line 837  void Brick::setToSize(escript::Data& out
837          const double xSize=getFirstCoordAndSpacing(0).second;          const double xSize=getFirstCoordAndSpacing(0).second;
838          const double ySize=getFirstCoordAndSpacing(1).second;          const double ySize=getFirstCoordAndSpacing(1).second;
839          const double zSize=getFirstCoordAndSpacing(2).second;          const double zSize=getFirstCoordAndSpacing(2).second;
840          const double size=min(min(xSize,ySize),zSize);          const double size=sqrt(xSize*xSize+ySize*ySize+zSize*zSize);
841  #pragma omp parallel for  #pragma omp parallel for
842          for (index_t k = 0; k < getNumElements(); ++k) {          for (index_t k = 0; k < getNumElements(); ++k) {
843              double* o = out.getSampleDataRW(k);              double* o = out.getSampleDataRW(k);
# Line 770  void Brick::assembleGradient(escript::Da Line 1079  void Brick::assembleGradient(escript::Da
1079    
1080      if (out.getFunctionSpace().getTypeCode() == Elements) {      if (out.getFunctionSpace().getTypeCode() == Elements) {
1081          out.requireWrite();          out.requireWrite();
1082  #pragma omp parallel for  #pragma omp parallel
1083          for (index_t k2=0; k2 < m_NE2; ++k2) {          {
1084              for (index_t k1=0; k1 < m_NE1; ++k1) {              vector<double> f_000(numComp);
1085                  for (index_t k0=0; k0 < m_NE0; ++k0) {              vector<double> f_001(numComp);
1086                      const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1));              vector<double> f_010(numComp);
1087                      const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1));              vector<double> f_011(numComp);
1088                      const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1));              vector<double> f_100(numComp);
1089                      const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1));              vector<double> f_101(numComp);
1090                      const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1));              vector<double> f_110(numComp);
1091                      const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1));              vector<double> f_111(numComp);
1092                      const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1));  #pragma omp for
1093                      const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1));              for (index_t k2=0; k2 < m_NE2; ++k2) {
1094                      double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1095                      for (index_t i=0; i < numComp; ++i) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1096                          const double V0=((f_100[i]-f_000[i])*C5 + (f_111[i]-f_011[i])*C0 + (f_101[i]+f_110[i]-f_001[i]-f_010[i])*C1) / h0;                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1097                          const double V1=((f_110[i]-f_010[i])*C5 + (f_101[i]-f_001[i])*C0 + (f_100[i]+f_111[i]-f_000[i]-f_011[i])*C1) / h0;                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1098                          const double V2=((f_101[i]-f_001[i])*C5 + (f_110[i]-f_010[i])*C0 + (f_100[i]+f_111[i]-f_000[i]-f_011[i])*C1) / h0;                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1099                          const double V3=((f_111[i]-f_011[i])*C5 + (f_100[i]-f_000[i])*C0 + (f_101[i]+f_110[i]-f_001[i]-f_010[i])*C1) / h0;                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1100                          const double V4=((f_010[i]-f_000[i])*C5 + (f_111[i]-f_101[i])*C0 + (f_011[i]+f_110[i]-f_001[i]-f_100[i])*C1) / h1;                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1101                          const double V5=((f_110[i]-f_100[i])*C5 + (f_011[i]-f_001[i])*C0 + (f_010[i]+f_111[i]-f_000[i]-f_101[i])*C1) / h1;                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1102                          const double V6=((f_011[i]-f_001[i])*C5 + (f_110[i]-f_100[i])*C0 + (f_010[i]+f_111[i]-f_000[i]-f_101[i])*C1) / h1;                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1103                          const double V7=((f_111[i]-f_101[i])*C5 + (f_010[i]-f_000[i])*C0 + (f_011[i]+f_110[i]-f_001[i]-f_100[i])*C1) / h1;                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1104                          const double V8=((f_001[i]-f_000[i])*C5 + (f_111[i]-f_110[i])*C0 + (f_011[i]+f_101[i]-f_010[i]-f_100[i])*C1) / h2;                          double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));
1105                          const double V9=((f_101[i]-f_100[i])*C5 + (f_011[i]-f_010[i])*C0 + (f_001[i]+f_111[i]-f_000[i]-f_110[i])*C1) / h2;                          for (index_t i=0; i < numComp; ++i) {
1106                          const double V10=((f_011[i]-f_010[i])*C5 + (f_101[i]-f_100[i])*C0 + (f_001[i]+f_111[i]-f_000[i]-f_110[i])*C1) / h2;                              const double V0=((f_100[i]-f_000[i])*C5 + (f_111[i]-f_011[i])*C0 + (f_101[i]+f_110[i]-f_001[i]-f_010[i])*C1) / h0;
1107                          const double V11=((f_111[i]-f_110[i])*C5 + (f_001[i]-f_000[i])*C0 + (f_011[i]+f_101[i]-f_010[i]-f_100[i])*C1) / h2;                              const double V1=((f_110[i]-f_010[i])*C5 + (f_101[i]-f_001[i])*C0 + (f_100[i]+f_111[i]-f_000[i]-f_011[i])*C1) / h0;
1108                          o[INDEX3(i,0,0,numComp,3)] = V0;                              const double V2=((f_101[i]-f_001[i])*C5 + (f_110[i]-f_010[i])*C0 + (f_100[i]+f_111[i]-f_000[i]-f_011[i])*C1) / h0;
1109                          o[INDEX3(i,1,0,numComp,3)] = V4;                              const double V3=((f_111[i]-f_011[i])*C5 + (f_100[i]-f_000[i])*C0 + (f_101[i]+f_110[i]-f_001[i]-f_010[i])*C1) / h0;
1110                          o[INDEX3(i,2,0,numComp,3)] = V8;                              const double V4=((f_010[i]-f_000[i])*C5 + (f_111[i]-f_101[i])*C0 + (f_011[i]+f_110[i]-f_001[i]-f_100[i])*C1) / h1;
1111                          o[INDEX3(i,0,1,numComp,3)] = V0;                              const double V5=((f_110[i]-f_100[i])*C5 + (f_011[i]-f_001[i])*C0 + (f_010[i]+f_111[i]-f_000[i]-f_101[i])*C1) / h1;
1112                          o[INDEX3(i,1,1,numComp,3)] = V5;                              const double V6=((f_011[i]-f_001[i])*C5 + (f_110[i]-f_100[i])*C0 + (f_010[i]+f_111[i]-f_000[i]-f_101[i])*C1) / h1;
1113                          o[INDEX3(i,2,1,numComp,3)] = V9;                              const double V7=((f_111[i]-f_101[i])*C5 + (f_010[i]-f_000[i])*C0 + (f_011[i]+f_110[i]-f_001[i]-f_100[i])*C1) / h1;
1114                          o[INDEX3(i,0,2,numComp,3)] = V1;                              const double V8=((f_001[i]-f_000[i])*C5 + (f_111[i]-f_110[i])*C0 + (f_011[i]+f_101[i]-f_010[i]-f_100[i])*C1) / h2;
1115                          o[INDEX3(i,1,2,numComp,3)] = V4;                              const double V9=((f_101[i]-f_100[i])*C5 + (f_011[i]-f_010[i])*C0 + (f_001[i]+f_111[i]-f_000[i]-f_110[i])*C1) / h2;
1116                          o[INDEX3(i,2,2,numComp,3)] = V10;                              const double V10=((f_011[i]-f_010[i])*C5 + (f_101[i]-f_100[i])*C0 + (f_001[i]+f_111[i]-f_000[i]-f_110[i])*C1) / h2;
1117                          o[INDEX3(i,0,3,numComp,3)] = V1;                              const double V11=((f_111[i]-f_110[i])*C5 + (f_001[i]-f_000[i])*C0 + (f_011[i]+f_101[i]-f_010[i]-f_100[i])*C1) / h2;
1118                          o[INDEX3(i,1,3,numComp,3)] = V5;                              o[INDEX3(i,0,0,numComp,3)] = V0;
1119                          o[INDEX3(i,2,3,numComp,3)] = V11;                              o[INDEX3(i,1,0,numComp,3)] = V4;
1120                          o[INDEX3(i,0,4,numComp,3)] = V2;                              o[INDEX3(i,2,0,numComp,3)] = V8;
1121                          o[INDEX3(i,1,4,numComp,3)] = V6;                              o[INDEX3(i,0,1,numComp,3)] = V0;
1122                          o[INDEX3(i,2,4,numComp,3)] = V8;                              o[INDEX3(i,1,1,numComp,3)] = V5;
1123                          o[INDEX3(i,0,5,numComp,3)] = V2;                              o[INDEX3(i,2,1,numComp,3)] = V9;
1124                          o[INDEX3(i,1,5,numComp,3)] = V7;                              o[INDEX3(i,0,2,numComp,3)] = V1;
1125                          o[INDEX3(i,2,5,numComp,3)] = V9;                              o[INDEX3(i,1,2,numComp,3)] = V4;
1126                          o[INDEX3(i,0,6,numComp,3)] = V3;                              o[INDEX3(i,2,2,numComp,3)] = V10;
1127                          o[INDEX3(i,1,6,numComp,3)] = V6;                              o[INDEX3(i,0,3,numComp,3)] = V1;
1128                          o[INDEX3(i,2,6,numComp,3)] = V10;                              o[INDEX3(i,1,3,numComp,3)] = V5;
1129                          o[INDEX3(i,0,7,numComp,3)] = V3;                              o[INDEX3(i,2,3,numComp,3)] = V11;
1130                          o[INDEX3(i,1,7,numComp,3)] = V7;                              o[INDEX3(i,0,4,numComp,3)] = V2;
1131                          o[INDEX3(i,2,7,numComp,3)] = V11;                              o[INDEX3(i,1,4,numComp,3)] = V6;
1132                      } // end of component loop i                              o[INDEX3(i,2,4,numComp,3)] = V8;
1133                  } // end of k0 loop                              o[INDEX3(i,0,5,numComp,3)] = V2;
1134              } // end of k1 loop                              o[INDEX3(i,1,5,numComp,3)] = V7;
1135          } // end of k2 loop                              o[INDEX3(i,2,5,numComp,3)] = V9;
1136                                o[INDEX3(i,0,6,numComp,3)] = V3;
1137                                o[INDEX3(i,1,6,numComp,3)] = V6;
1138                                o[INDEX3(i,2,6,numComp,3)] = V10;
1139                                o[INDEX3(i,0,7,numComp,3)] = V3;
1140                                o[INDEX3(i,1,7,numComp,3)] = V7;
1141                                o[INDEX3(i,2,7,numComp,3)] = V11;
1142                            } // end of component loop i
1143                        } // end of k0 loop
1144                    } // end of k1 loop
1145                } // end of k2 loop
1146            } // end of parallel section
1147      } else if (out.getFunctionSpace().getTypeCode() == ReducedElements) {      } else if (out.getFunctionSpace().getTypeCode() == ReducedElements) {
1148          out.requireWrite();          out.requireWrite();
1149  #pragma omp parallel for  #pragma omp parallel
1150          for (index_t k2=0; k2 < m_NE2; ++k2) {          {
1151              for (index_t k1=0; k1 < m_NE1; ++k1) {              vector<double> f_000(numComp);
1152                  for (index_t k0=0; k0 < m_NE0; ++k0) {              vector<double> f_001(numComp);
1153                      const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1));              vector<double> f_010(numComp);
1154                      const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1));              vector<double> f_011(numComp);
1155                      const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1));              vector<double> f_100(numComp);
1156                      const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1));              vector<double> f_101(numComp);
1157                      const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1));              vector<double> f_110(numComp);
1158                      const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1));              vector<double> f_111(numComp);
1159                      const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1));  #pragma omp for
1160                      const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1));              for (index_t k2=0; k2 < m_NE2; ++k2) {
1161                      double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1162                      for (index_t i=0; i < numComp; ++i) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1163                          o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1164                          o[INDEX3(i,1,0,numComp,3)] = (f_010[i]+f_011[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_100[i]-f_101[i])*C3 / h1;                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1165                          o[INDEX3(i,2,0,numComp,3)] = (f_001[i]+f_011[i]+f_101[i]+f_111[i]-f_000[i]-f_010[i]-f_100[i]-f_110[i])*C3 / h2;                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1166                      } // end of component loop i                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1167                  } // end of k0 loop                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1168              } // end of k1 loop                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1169          } // end of k2 loop                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1170                            memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1171                            double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));
1172                            for (index_t i=0; i < numComp; ++i) {
1173                                o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;
1174                                o[INDEX3(i,1,0,numComp,3)] = (f_010[i]+f_011[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_100[i]-f_101[i])*C3 / h1;
1175                                o[INDEX3(i,2,0,numComp,3)] = (f_001[i]+f_011[i]+f_101[i]+f_111[i]-f_000[i]-f_010[i]-f_100[i]-f_110[i])*C3 / h2;
1176                            } // end of component loop i
1177                        } // end of k0 loop
1178                    } // end of k1 loop
1179                } // end of k2 loop
1180            } // end of parallel section
1181      } else if (out.getFunctionSpace().getTypeCode() == FaceElements) {      } else if (out.getFunctionSpace().getTypeCode() == FaceElements) {
1182          out.requireWrite();          out.requireWrite();
1183  #pragma omp parallel  #pragma omp parallel
1184          {          {
1185                vector<double> f_000(numComp);
1186                vector<double> f_001(numComp);
1187                vector<double> f_010(numComp);
1188                vector<double> f_011(numComp);
1189                vector<double> f_100(numComp);
1190                vector<double> f_101(numComp);
1191                vector<double> f_110(numComp);
1192                vector<double> f_111(numComp);
1193              if (m_faceOffset[0] > -1) {              if (m_faceOffset[0] > -1) {
1194  #pragma omp for nowait  #pragma omp for nowait
1195                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1196                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
1197                          const double* f_000 = in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1198                          const double* f_001 = in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1199                          const double* f_101 = in.getSampleDataRO(INDEX3(1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1200                          const double* f_111 = in.getSampleDataRO(INDEX3(1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1201                          const double* f_110 = in.getSampleDataRO(INDEX3(1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1202                          const double* f_011 = in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1203                          const double* f_010 = in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1204                          const double* f_100 = in.getSampleDataRO(INDEX3(1,k1,k2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1205                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));
1206                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1207                              const double V0=((f_010[i]-f_000[i])*C6 + (f_011[i]-f_001[i])*C2) / h1;                              const double V0=((f_010[i]-f_000[i])*C6 + (f_011[i]-f_001[i])*C2) / h1;
# Line 889  void Brick::assembleGradient(escript::Da Line 1228  void Brick::assembleGradient(escript::Da
1228  #pragma omp for nowait  #pragma omp for nowait
1229                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1230                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
1231                          const double* f_000 = in.getSampleDataRO(INDEX3(m_N0-2,k1,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(m_N0-2,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1232                          const double* f_001 = in.getSampleDataRO(INDEX3(m_N0-2,k1,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(m_N0-2,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1233                          const double* f_101 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1234                          const double* f_111 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1235                          const double* f_110 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1236                          const double* f_011 = in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1237                          const double* f_010 = in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1238                          const double* f_100 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1239                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));
1240                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1241                              const double V0=((f_110[i]-f_100[i])*C6 + (f_111[i]-f_101[i])*C2) / h1;                              const double V0=((f_110[i]-f_100[i])*C6 + (f_111[i]-f_101[i])*C2) / h1;
# Line 923  void Brick::assembleGradient(escript::Da Line 1262  void Brick::assembleGradient(escript::Da
1262  #pragma omp for nowait  #pragma omp for nowait
1263                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1264                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1265                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1)), numComp*sizeof(double));
1266                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1267                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,1,k2, m_N0,m_N1)), numComp*sizeof(double));
1268                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1269                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,1,k2+1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1)), numComp*sizeof(double));
1270                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1271                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,1,k2+1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,1,k2, m_N0,m_N1)), numComp*sizeof(double));
1272                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,1,k2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1273                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));
1274                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1275                              const double V0=((f_100[i]-f_000[i])*C6 + (f_101[i]-f_001[i])*C2) / h0;                              const double V0=((f_100[i]-f_000[i])*C6 + (f_101[i]-f_001[i])*C2) / h0;
# Line 956  void Brick::assembleGradient(escript::Da Line 1295  void Brick::assembleGradient(escript::Da
1295  #pragma omp for nowait  #pragma omp for nowait
1296                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1297                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1298                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,m_N1-2,k2, m_N0,m_N1)), numComp*sizeof(double));
1299                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,m_N1-2,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1300                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
1301                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1302                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,m_N1-2,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2, m_N0,m_N1)), numComp*sizeof(double));
1303                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,m_N1-2,k2+1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1304                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2+1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
1305                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1306                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));
1307                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1308                              const double V0=((f_110[i]-f_010[i])*C6 + (f_111[i]-f_011[i])*C2) / h0;                              const double V0=((f_110[i]-f_010[i])*C6 + (f_111[i]-f_011[i])*C2) / h0;
# Line 990  void Brick::assembleGradient(escript::Da Line 1329  void Brick::assembleGradient(escript::Da
1329  #pragma omp for nowait  #pragma omp for nowait
1330                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1331                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1332                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1)), numComp*sizeof(double));
1333                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,1, m_N0,m_N1)), numComp*sizeof(double));
1334                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
1335                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,1, m_N0,m_N1)), numComp*sizeof(double));
1336                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1)), numComp*sizeof(double));
1337                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,1, m_N0,m_N1)), numComp*sizeof(double));
1338                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
1339                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,1, m_N0,m_N1)), numComp*sizeof(double));
1340                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));
1341                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1342                              const double V0=((f_100[i]-f_000[i])*C6 + (f_110[i]-f_010[i])*C2) / h0;                              const double V0=((f_100[i]-f_000[i])*C6 + (f_110[i]-f_010[i])*C2) / h0;
# Line 1024  void Brick::assembleGradient(escript::Da Line 1363  void Brick::assembleGradient(escript::Da
1363  #pragma omp for nowait  #pragma omp for nowait
1364                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1365                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1366                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1367                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1368                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1369                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1370                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1371                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1372                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1373                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1374                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));
1375                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1376                              const double V0=((f_101[i]-f_001[i])*C6 + (f_111[i]-f_011[i])*C2) / h0;                              const double V0=((f_101[i]-f_001[i])*C6 + (f_111[i]-f_011[i])*C2) / h0;
# Line 1059  void Brick::assembleGradient(escript::Da Line 1398  void Brick::assembleGradient(escript::Da
1398          out.requireWrite();          out.requireWrite();
1399  #pragma omp parallel  #pragma omp parallel
1400          {          {
1401                vector<double> f_000(numComp);
1402                vector<double> f_001(numComp);
1403                vector<double> f_010(numComp);
1404                vector<double> f_011(numComp);
1405                vector<double> f_100(numComp);
1406                vector<double> f_101(numComp);
1407                vector<double> f_110(numComp);
1408                vector<double> f_111(numComp);
1409              if (m_faceOffset[0] > -1) {              if (m_faceOffset[0] > -1) {
1410  #pragma omp for nowait  #pragma omp for nowait
1411                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1412                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
1413                          const double* f_000 = in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1414                          const double* f_001 = in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1415                          const double* f_101 = in.getSampleDataRO(INDEX3(1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1416                          const double* f_011 = in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1417                          const double* f_100 = in.getSampleDataRO(INDEX3(1,k1,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1418                          const double* f_110 = in.getSampleDataRO(INDEX3(1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1419                          const double* f_010 = in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1420                          const double* f_111 = in.getSampleDataRO(INDEX3(1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1421                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));
1422                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1423                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;
# Line 1084  void Brick::assembleGradient(escript::Da Line 1431  void Brick::assembleGradient(escript::Da
1431  #pragma omp for nowait  #pragma omp for nowait
1432                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1433                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
1434                          const double* f_000 = in.getSampleDataRO(INDEX3(m_N0-2,k1,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(m_N0-2,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1435                          const double* f_001 = in.getSampleDataRO(INDEX3(m_N0-2,k1,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(m_N0-2,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1436                          const double* f_101 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1437                          const double* f_011 = in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1438                          const double* f_100 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
1439                          const double* f_110 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1440                          const double* f_010 = in.getSampleDataRO(INDEX3(m_N0-2,k1+1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
1441                          const double* f_111 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1442                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));
1443                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1444                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]+f_110[i]+f_111[i]-f_000[i]-f_001[i]-f_010[i]-f_011[i])*C3 / h0;
# Line 1105  void Brick::assembleGradient(escript::Da Line 1452  void Brick::assembleGradient(escript::Da
1452  #pragma omp for nowait  #pragma omp for nowait
1453                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1454                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1455                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1)), numComp*sizeof(double));
1456                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1457                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,1,k2, m_N0,m_N1)), numComp*sizeof(double));
1458                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1459                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,1,k2+1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1)), numComp*sizeof(double));
1460                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1461                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,1,k2, m_N0,m_N1)), numComp*sizeof(double));
1462                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1463                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));
1464                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1465                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]-f_000[i]-f_001[i])*C4 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_101[i]-f_000[i]-f_001[i])*C4 / h0;
# Line 1126  void Brick::assembleGradient(escript::Da Line 1473  void Brick::assembleGradient(escript::Da
1473  #pragma omp for nowait  #pragma omp for nowait
1474                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
1475                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1476                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,m_N1-2,k2, m_N0,m_N1)), numComp*sizeof(double));
1477                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,m_N1-2,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1478                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
1479                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1480                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,m_N1-2,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2, m_N0,m_N1)), numComp*sizeof(double));
1481                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2+1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1482                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,m_N1-2,k2+1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
1483                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,m_N1-2,k2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
1484                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));
1485                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1486                              o[INDEX3(i,0,0,numComp,3)] = (f_110[i]+f_111[i]-f_010[i]-f_011[i])*C4 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_110[i]+f_111[i]-f_010[i]-f_011[i])*C4 / h0;
# Line 1147  void Brick::assembleGradient(escript::Da Line 1494  void Brick::assembleGradient(escript::Da
1494  #pragma omp for nowait  #pragma omp for nowait
1495                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1496                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1497                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1)), numComp*sizeof(double));
1498                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,1, m_N0,m_N1)), numComp*sizeof(double));
1499                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
1500                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,1, m_N0,m_N1)), numComp*sizeof(double));
1501                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1)), numComp*sizeof(double));
1502                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,1, m_N0,m_N1)), numComp*sizeof(double));
1503                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
1504                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,1, m_N0,m_N1)), numComp*sizeof(double));
1505                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));
1506                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1507                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_110[i]-f_000[i]-f_010[i])*C4 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_100[i]+f_110[i]-f_000[i]-f_010[i])*C4 / h0;
# Line 1168  void Brick::assembleGradient(escript::Da Line 1515  void Brick::assembleGradient(escript::Da
1515  #pragma omp for nowait  #pragma omp for nowait
1516                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
1517                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
1518                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1519                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1520                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1521                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1522                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1523                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1524                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-2, m_N0,m_N1)), numComp*sizeof(double));
1525                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-2, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
1526                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));
1527                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
1528                              o[INDEX3(i,0,0,numComp,3)] = (f_101[i]+f_111[i]-f_001[i]-f_011[i])*C4 / h0;                              o[INDEX3(i,0,0,numComp,3)] = (f_101[i]+f_111[i]-f_001[i]-f_011[i])*C4 / h0;
# Line 1199  void Brick::assembleIntegrate(vector<dou Line 1546  void Brick::assembleIntegrate(vector<dou
1546      const index_t left = (m_offset0==0 ? 0 : 1);      const index_t left = (m_offset0==0 ? 0 : 1);
1547      const index_t bottom = (m_offset1==0 ? 0 : 1);      const index_t bottom = (m_offset1==0 ? 0 : 1);
1548      const index_t front = (m_offset2==0 ? 0 : 1);      const index_t front = (m_offset2==0 ? 0 : 1);
1549      if (arg.getFunctionSpace().getTypeCode() == Elements) {      const int fs = arg.getFunctionSpace().getTypeCode();
1550        if (fs == Elements && arg.actsExpanded()) {
1551          const double w_0 = h0*h1*h2/8.;          const double w_0 = h0*h1*h2/8.;
1552  #pragma omp parallel  #pragma omp parallel
1553          {          {
# Line 1228  void Brick::assembleIntegrate(vector<dou Line 1576  void Brick::assembleIntegrate(vector<dou
1576              for (index_t i=0; i<numComp; i++)              for (index_t i=0; i<numComp; i++)
1577                  integrals[i]+=int_local[i];                  integrals[i]+=int_local[i];
1578          } // end of parallel section          } // end of parallel section
1579      } else if (arg.getFunctionSpace().getTypeCode() == ReducedElements) {  
1580        } else if (fs==ReducedElements || (fs==Elements && !arg.actsExpanded())) {
1581          const double w_0 = h0*h1*h2;          const double w_0 = h0*h1*h2;
1582  #pragma omp parallel  #pragma omp parallel
1583          {          {
# Line 1249  void Brick::assembleIntegrate(vector<dou Line 1598  void Brick::assembleIntegrate(vector<dou
1598              for (index_t i=0; i<numComp; i++)              for (index_t i=0; i<numComp; i++)
1599                  integrals[i]+=int_local[i];                  integrals[i]+=int_local[i];
1600          } // end of parallel section          } // end of parallel section
1601      } else if (arg.getFunctionSpace().getTypeCode() == FaceElements) {  
1602        } else if (fs == FaceElements && arg.actsExpanded()) {
1603          const double w_0 = h1*h2/4.;          const double w_0 = h1*h2/4.;
1604          const double w_1 = h0*h2/4.;          const double w_1 = h0*h2/4.;
1605          const double w_2 = h0*h1/4.;          const double w_2 = h0*h1/4.;
# Line 1357  void Brick::assembleIntegrate(vector<dou Line 1707  void Brick::assembleIntegrate(vector<dou
1707                  integrals[i]+=int_local[i];                  integrals[i]+=int_local[i];
1708          } // end of parallel section          } // end of parallel section
1709    
1710      } else if (arg.getFunctionSpace().getTypeCode() == ReducedFaceElements) {      } else if (fs==ReducedFaceElements || (fs==FaceElements && !arg.actsExpanded())) {
1711          const double w_0 = h1*h2;          const double w_0 = h1*h2;
1712          const double w_1 = h0*h2;          const double w_1 = h0*h2;
1713          const double w_2 = h0*h1;          const double w_2 = h0*h1;
# Line 1440  void Brick::assembleIntegrate(vector<dou Line 1790  void Brick::assembleIntegrate(vector<dou
1790              for (index_t i=0; i<numComp; i++)              for (index_t i=0; i<numComp; i++)
1791                  integrals[i]+=int_local[i];                  integrals[i]+=int_local[i];
1792          } // end of parallel section          } // end of parallel section
1793        } // function space selector
     }  
1794  }  }
1795    
1796  //protected  //protected
# Line 1521  void Brick::dofToNodes(escript::Data& ou Line 1870  void Brick::dofToNodes(escript::Data& ou
1870                  : &buffer[(m_dofMap[i]-numDOF)*numComp]);                  : &buffer[(m_dofMap[i]-numDOF)*numComp]);
1871          copy(src, src+numComp, out.getSampleDataRW(i));          copy(src, src+numComp, out.getSampleDataRW(i));
1872      }      }
1873        Paso_Coupler_free(coupler);
1874  }  }
1875    
1876  //private  //private
# Line 1763  void Brick::createPattern() Line 2113  void Brick::createPattern()
2113                          offsetInShared.push_back(offsetInShared.back()+nDOF0);                          offsetInShared.push_back(offsetInShared.back()+nDOF0);
2114                          const int firstDOF=(i1+1)/2*nDOF0*(nDOF1-1)                          const int firstDOF=(i1+1)/2*nDOF0*(nDOF1-1)
2115                                             +(i2+1)/2*nDOF0*nDOF1*(nDOF2-1);                                             +(i2+1)/2*nDOF0*nDOF1*(nDOF2-1);
2116                          const int firstNode=(i1+1)/2*m_N0*(m_N1-1)                          const int firstNode=left+(i1+1)/2*m_N0*(m_N1-1)
2117                                              +(i2+1)/2*m_N0*m_N1*(m_N2-1);                                              +(i2+1)/2*m_N0*m_N1*(m_N2-1);
2118                          for (dim_t i=0; i<nDOF0; i++, numShared++) {                          for (dim_t i=0; i<nDOF0; i++, numShared++) {
2119                              sendShared.push_back(firstDOF+i);                              sendShared.push_back(firstDOF+i);
# Line 1780  void Brick::createPattern() Line 2130  void Brick::createPattern()
2130                          offsetInShared.push_back(offsetInShared.back()+nDOF1);                          offsetInShared.push_back(offsetInShared.back()+nDOF1);
2131                          const int firstDOF=(i0+1)/2*(nDOF0-1)                          const int firstDOF=(i0+1)/2*(nDOF0-1)
2132                                             +(i2+1)/2*nDOF0*nDOF1*(nDOF2-1);                                             +(i2+1)/2*nDOF0*nDOF1*(nDOF2-1);
2133                          const int firstNode=(i0+1)/2*(m_N0-1)                          const int firstNode=bottom*m_N0
2134                                                +(i0+1)/2*(m_N0-1)
2135                                              +(i2+1)/2*m_N0*m_N1*(m_N2-1);                                              +(i2+1)/2*m_N0*m_N1*(m_N2-1);
2136                          for (dim_t i=0; i<nDOF1; i++, numShared++) {                          for (dim_t i=0; i<nDOF1; i++, numShared++) {
2137                              sendShared.push_back(firstDOF+i*nDOF0);                              sendShared.push_back(firstDOF+i*nDOF0);
# Line 1797  void Brick::createPattern() Line 2148  void Brick::createPattern()
2148                          offsetInShared.push_back(offsetInShared.back()+nDOF2);                          offsetInShared.push_back(offsetInShared.back()+nDOF2);
2149                          const int firstDOF=(i0+1)/2*(nDOF0-1)                          const int firstDOF=(i0+1)/2*(nDOF0-1)
2150                                             +(i1+1)/2*nDOF0*(nDOF1-1);                                             +(i1+1)/2*nDOF0*(nDOF1-1);
2151                          const int firstNode=(i0+1)/2*(m_N0-1)                          const int firstNode=front*m_N0*m_N1
2152                                                +(i0+1)/2*(m_N0-1)
2153                                              +(i1+1)/2*m_N0*(m_N1-1);                                              +(i1+1)/2*m_N0*(m_N1-1);
2154                          for (dim_t i=0; i<nDOF2; i++, numShared++) {                          for (dim_t i=0; i<nDOF2; i++, numShared++) {
2155                              sendShared.push_back(firstDOF+i*nDOF0*nDOF1);                              sendShared.push_back(firstDOF+i*nDOF0*nDOF1);
# Line 1956  void Brick::interpolateNodesOnElements(e Line 2308  void Brick::interpolateNodesOnElements(e
2308      if (reduced) {      if (reduced) {
2309          out.requireWrite();          out.requireWrite();
2310          const double c0 = .125;          const double c0 = .125;
2311  #pragma omp parallel for  #pragma omp parallel
2312          for (index_t k2=0; k2 < m_NE2; ++k2) {          {
2313              for (index_t k1=0; k1 < m_NE1; ++k1) {              vector<double> f_000(numComp);
2314                  for (index_t k0=0; k0 < m_NE0; ++k0) {              vector<double> f_001(numComp);
2315                      const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1));              vector<double> f_010(numComp);
2316                      const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1));              vector<double> f_011(numComp);
2317                      const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1));              vector<double> f_100(numComp);
2318                      const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1));              vector<double> f_101(numComp);
2319                      const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1));              vector<double> f_110(numComp);
2320                      const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1));              vector<double> f_111(numComp);
2321                      const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1));  #pragma omp for
2322                      const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1));              for (index_t k2=0; k2 < m_NE2; ++k2) {
2323                      double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2324                      for (index_t i=0; i < numComp; ++i) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2325                          o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_010[i] + f_011[i] + f_100[i] + f_101[i] + f_110[i] + f_111[i]);                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2326                      } // end of component loop i                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2327                  } // end of k0 loop                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2328              } // end of k1 loop                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2329          } // end of k2 loop                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2330                            memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2331                            memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2332                            memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2333                            double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));
2334                            for (index_t i=0; i < numComp; ++i) {
2335                                o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_010[i] + f_011[i] + f_100[i] + f_101[i] + f_110[i] + f_111[i]);
2336                            } // end of component loop i
2337                        } // end of k0 loop
2338                    } // end of k1 loop
2339                } // end of k2 loop
2340            } // end of parallel section
2341      } else {      } else {
2342          out.requireWrite();          out.requireWrite();
2343          const double c0 = .0094373878376559314545;          const double c0 = .0094373878376559314545;
2344          const double c1 = .035220810900864519624;          const double c1 = .035220810900864519624;
2345          const double c2 = .13144585576580214704;          const double c2 = .13144585576580214704;
2346          const double c3 = .49056261216234406855;          const double c3 = .49056261216234406855;
2347  #pragma omp parallel for  #pragma omp parallel
2348          for (index_t k2=0; k2 < m_NE2; ++k2) {          {
2349              for (index_t k1=0; k1 < m_NE1; ++k1) {              vector<double> f_000(numComp);
2350                  for (index_t k0=0; k0 < m_NE0; ++k0) {              vector<double> f_001(numComp);
2351                      const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1));              vector<double> f_010(numComp);
2352                      const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1));              vector<double> f_011(numComp);
2353                      const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1));              vector<double> f_100(numComp);
2354                      const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1));              vector<double> f_101(numComp);
2355                      const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1));              vector<double> f_110(numComp);
2356                      const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1));              vector<double> f_111(numComp);
2357                      const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1));  #pragma omp for
2358                      const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1));              for (index_t k2=0; k2 < m_NE2; ++k2) {
2359                      double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2360                      for (index_t i=0; i < numComp; ++i) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2361                          o[INDEX2(i,numComp,0)] = f_000[i]*c3 + f_111[i]*c0 + c2*(f_001[i] + f_010[i] + f_100[i]) + c1*(f_011[i] + f_101[i] + f_110[i]);                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2362                          o[INDEX2(i,numComp,1)] = f_011[i]*c0 + f_100[i]*c3 + c2*(f_000[i] + f_101[i] + f_110[i]) + c1*(f_001[i] + f_010[i] + f_111[i]);                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2363                          o[INDEX2(i,numComp,2)] = f_010[i]*c3 + f_101[i]*c0 + c2*(f_000[i] + f_011[i] + f_110[i]) + c1*(f_001[i] + f_100[i] + f_111[i]);                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2364                          o[INDEX2(i,numComp,3)] = f_001[i]*c0 + f_110[i]*c3 + c2*(f_010[i] + f_100[i] + f_111[i]) + c1*(f_000[i] + f_011[i] + f_101[i]);                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2365                          o[INDEX2(i,numComp,4)] = f_001[i]*c3 + f_110[i]*c0 + c2*(f_000[i] + f_011[i] + f_101[i]) + c1*(f_010[i] + f_100[i] + f_111[i]);                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2366                          o[INDEX2(i,numComp,5)] = f_010[i]*c0 + f_101[i]*c3 + c2*(f_001[i] + f_100[i] + f_111[i]) + c1*(f_000[i] + f_011[i] + f_110[i]);                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2367                          o[INDEX2(i,numComp,6)] = f_011[i]*c3 + f_100[i]*c0 + c2*(f_001[i] + f_010[i] + f_111[i]) + c1*(f_000[i] + f_101[i] + f_110[i]);                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2368                          o[INDEX2(i,numComp,7)] = f_000[i]*c0 + f_111[i]*c3 + c2*(f_011[i] + f_101[i] + f_110[i]) + c1*(f_001[i] + f_010[i] + f_100[i]);                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2369                      } // end of component loop i                          double* o = out.getSampleDataRW(INDEX3(k0,k1,k2,m_NE0,m_NE1));
2370                  } // end of k0 loop                          for (index_t i=0; i < numComp; ++i) {
2371              } // end of k1 loop                              o[INDEX2(i,numComp,0)] = f_000[i]*c3 + f_111[i]*c0 + c2*(f_001[i] + f_010[i] + f_100[i]) + c1*(f_011[i] + f_101[i] + f_110[i]);
2372          } // end of k2 loop                              o[INDEX2(i,numComp,1)] = f_011[i]*c0 + f_100[i]*c3 + c2*(f_000[i] + f_101[i] + f_110[i]) + c1*(f_001[i] + f_010[i] + f_111[i]);
2373                                o[INDEX2(i,numComp,2)] = f_010[i]*c3 + f_101[i]*c0 + c2*(f_000[i] + f_011[i] + f_110[i]) + c1*(f_001[i] + f_100[i] + f_111[i]);
2374                                o[INDEX2(i,numComp,3)] = f_001[i]*c0 + f_110[i]*c3 + c2*(f_010[i] + f_100[i] + f_111[i]) + c1*(f_000[i] + f_011[i] + f_101[i]);
2375                                o[INDEX2(i,numComp,4)] = f_001[i]*c3 + f_110[i]*c0 + c2*(f_000[i] + f_011[i] + f_101[i]) + c1*(f_010[i] + f_100[i] + f_111[i]);
2376                                o[INDEX2(i,numComp,5)] = f_010[i]*c0 + f_101[i]*c3 + c2*(f_001[i] + f_100[i] + f_111[i]) + c1*(f_000[i] + f_011[i] + f_110[i]);
2377                                o[INDEX2(i,numComp,6)] = f_011[i]*c3 + f_100[i]*c0 + c2*(f_001[i] + f_010[i] + f_111[i]) + c1*(f_000[i] + f_101[i] + f_110[i]);
2378                                o[INDEX2(i,numComp,7)] = f_000[i]*c0 + f_111[i]*c3 + c2*(f_011[i] + f_101[i] + f_110[i]) + c1*(f_001[i] + f_010[i] + f_100[i]);
2379                            } // end of component loop i
2380                        } // end of k0 loop
2381                    } // end of k1 loop
2382                } // end of k2 loop
2383            } // end of parallel section
2384      }      }
2385  }  }
2386    
# Line 2020  void Brick::interpolateNodesOnFaces(escr Line 2394  void Brick::interpolateNodesOnFaces(escr
2394          const double c0 = .25;          const double c0 = .25;
2395  #pragma omp parallel  #pragma omp parallel
2396          {          {
2397                vector<double> f_000(numComp);
2398                vector<double> f_001(numComp);
2399                vector<double> f_010(numComp);
2400                vector<double> f_011(numComp);
2401                vector<double> f_100(numComp);
2402                vector<double> f_101(numComp);
2403                vector<double> f_110(numComp);
2404                vector<double> f_111(numComp);
2405              if (m_faceOffset[0] > -1) {              if (m_faceOffset[0] > -1) {
2406  #pragma omp for nowait  #pragma omp for nowait
2407                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2408                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
2409                          const double* f_011 = in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2410                          const double* f_010 = in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2411                          const double* f_001 = in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2412                          const double* f_000 = in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2413                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));
2414                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2415                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_010[i] + f_011[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_010[i] + f_011[i]);
# Line 2039  void Brick::interpolateNodesOnFaces(escr Line 2421  void Brick::interpolateNodesOnFaces(escr
2421  #pragma omp for nowait  #pragma omp for nowait
2422                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2423                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
2424                          const double* f_110 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2425                          const double* f_100 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2426                          const double* f_101 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2427                          const double* f_111 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2428                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));
2429                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2430                              o[INDEX2(i,numComp,0)] = c0*(f_100[i] + f_101[i] + f_110[i] + f_111[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_100[i] + f_101[i] + f_110[i] + f_111[i]);
# Line 2054  void Brick::interpolateNodesOnFaces(escr Line 2436  void Brick::interpolateNodesOnFaces(escr
2436  #pragma omp for nowait  #pragma omp for nowait
2437                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2438                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2439                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1)), numComp*sizeof(double));
2440                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2441                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1)), numComp*sizeof(double));
2442                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2443                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));
2444                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2445                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_100[i] + f_101[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_001[i] + f_100[i] + f_101[i]);
# Line 2069  void Brick::interpolateNodesOnFaces(escr Line 2451  void Brick::interpolateNodesOnFaces(escr
2451  #pragma omp for nowait  #pragma omp for nowait
2452                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2453                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2454                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
2455                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2456                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
2457                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2458                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));
2459                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2460                              o[INDEX2(i,numComp,0)] = c0*(f_010[i] + f_011[i] + f_110[i] + f_111[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_010[i] + f_011[i] + f_110[i] + f_111[i]);
# Line 2084  void Brick::interpolateNodesOnFaces(escr Line 2466  void Brick::interpolateNodesOnFaces(escr
2466  #pragma omp for nowait  #pragma omp for nowait
2467                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2468                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2469                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1)), numComp*sizeof(double));
2470                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
2471                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1)), numComp*sizeof(double));
2472                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
2473                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));
2474                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2475                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_010[i] + f_100[i] + f_110[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_000[i] + f_010[i] + f_100[i] + f_110[i]);
# Line 2099  void Brick::interpolateNodesOnFaces(escr Line 2481  void Brick::interpolateNodesOnFaces(escr
2481  #pragma omp for nowait  #pragma omp for nowait
2482                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2483                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2484                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2485                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2486                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2487                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2488                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));
2489                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2490                              o[INDEX2(i,numComp,0)] = c0*(f_001[i] + f_011[i] + f_101[i] + f_111[i]);                              o[INDEX2(i,numComp,0)] = c0*(f_001[i] + f_011[i] + f_101[i] + f_111[i]);
# Line 2118  void Brick::interpolateNodesOnFaces(escr Line 2500  void Brick::interpolateNodesOnFaces(escr
2500          const double c2 = 0.62200846792814621559;          const double c2 = 0.62200846792814621559;
2501  #pragma omp parallel  #pragma omp parallel
2502          {          {
2503                vector<double> f_000(numComp);
2504                vector<double> f_001(numComp);
2505                vector<double> f_010(numComp);
2506                vector<double> f_011(numComp);
2507                vector<double> f_100(numComp);
2508                vector<double> f_101(numComp);
2509                vector<double> f_110(numComp);
2510                vector<double> f_111(numComp);
2511              if (m_faceOffset[0] > -1) {              if (m_faceOffset[0] > -1) {
2512  #pragma omp for nowait  #pragma omp for nowait
2513                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2514                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
2515                          const double* f_000 = in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(0,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2516                          const double* f_001 = in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(0,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2517                          const double* f_011 = in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2518                          const double* f_010 = in.getSampleDataRO(INDEX3(0,k1+1,k2, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(0,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2519                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[0]+INDEX2(k1,k2,m_NE1));
2520                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2521                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_011[i]*c0 + c1*(f_001[i] + f_010[i]);                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_011[i]*c0 + c1*(f_001[i] + f_010[i]);
# Line 2140  void Brick::interpolateNodesOnFaces(escr Line 2530  void Brick::interpolateNodesOnFaces(escr
2530  #pragma omp for nowait  #pragma omp for nowait
2531                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2532                      for (index_t k1=0; k1 < m_NE1; ++k1) {                      for (index_t k1=0; k1 < m_NE1; ++k1) {
2533                          const double* f_101 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1)), numComp*sizeof(double));
2534                          const double* f_100 = in.getSampleDataRO(INDEX3(m_N0-1,k1,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(m_N0-1,k1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2535                          const double* f_110 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2, m_N0,m_N1)), numComp*sizeof(double));
2536                          const double* f_111 = in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(m_N0-1,k1+1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2537                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));                          double* o = out.getSampleDataRW(m_faceOffset[1]+INDEX2(k1,k2,m_NE1));
2538                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2539                              o[INDEX2(i,numComp,0)] = f_100[i]*c2 + f_111[i]*c0 + c1*(f_101[i] + f_110[i]);                              o[INDEX2(i,numComp,0)] = f_100[i]*c2 + f_111[i]*c0 + c1*(f_101[i] + f_110[i]);
# Line 2158  void Brick::interpolateNodesOnFaces(escr Line 2548  void Brick::interpolateNodesOnFaces(escr
2548  #pragma omp for nowait  #pragma omp for nowait
2549                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2550                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2551                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,0,k2, m_N0,m_N1)), numComp*sizeof(double));
2552                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2553                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1)), numComp*sizeof(double));
2554                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,0,k2, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,0,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2555                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[2]+INDEX2(k0,k2,m_NE0));
2556                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2557                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_101[i]*c0 + c1*(f_001[i] + f_100[i]);                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_101[i]*c0 + c1*(f_001[i] + f_100[i]);
# Line 2176  void Brick::interpolateNodesOnFaces(escr Line 2566  void Brick::interpolateNodesOnFaces(escr
2566  #pragma omp for nowait  #pragma omp for nowait
2567                  for (index_t k2=0; k2 < m_NE2; ++k2) {                  for (index_t k2=0; k2 < m_NE2; ++k2) {
2568                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2569                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
2570                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2571                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,m_N1-1,k2, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2, m_N0,m_N1)), numComp*sizeof(double));
2572                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,m_N1-1,k2+1, m_N0,m_N1)), numComp*sizeof(double));
2573                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[3]+INDEX2(k0,k2,m_NE0));
2574                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2575                              o[INDEX2(i,numComp,0)] = f_010[i]*c2 + f_111[i]*c0 + c1*(f_011[i] + f_110[i]);                              o[INDEX2(i,numComp,0)] = f_010[i]*c2 + f_111[i]*c0 + c1*(f_011[i] + f_110[i]);
# Line 2194  void Brick::interpolateNodesOnFaces(escr Line 2584  void Brick::interpolateNodesOnFaces(escr
2584  #pragma omp for nowait  #pragma omp for nowait
2585                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2586                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2587                          const double* f_000 = in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1));                          memcpy(&f_000[0], in.getSampleDataRO(INDEX3(k0,k1,0, m_N0,m_N1)), numComp*sizeof(double));
2588                          const double* f_100 = in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1));                          memcpy(&f_010[0], in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
2589                          const double* f_110 = in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1));                          memcpy(&f_100[0], in.getSampleDataRO(INDEX3(k0+1,k1,0, m_N0,m_N1)), numComp*sizeof(double));
2590                          const double* f_010 = in.getSampleDataRO(INDEX3(k0,k1+1,0, m_N0,m_N1));                          memcpy(&f_110[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,0, m_N0,m_N1)), numComp*sizeof(double));
2591                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[4]+INDEX2(k0,k1,m_NE0));
2592                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2593                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_110[i]*c0 + c1*(f_010[i] + f_100[i]);                              o[INDEX2(i,numComp,0)] = f_000[i]*c2 + f_110[i]*c0 + c1*(f_010[i] + f_100[i]);
# Line 2212  void Brick::interpolateNodesOnFaces(escr Line 2602  void Brick::interpolateNodesOnFaces(escr
2602  #pragma omp for nowait  #pragma omp for nowait
2603                  for (index_t k1=0; k1 < m_NE1; ++k1) {                  for (index_t k1=0; k1 < m_NE1; ++k1) {
2604                      for (index_t k0=0; k0 < m_NE0; ++k0) {                      for (index_t k0=0; k0 < m_NE0; ++k0) {
2605                          const double* f_001 = in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_001[0], in.getSampleDataRO(INDEX3(k0,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2606                          const double* f_101 = in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1));                          memcpy(&f_011[0], in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2607                          const double* f_011 = in.getSampleDataRO(INDEX3(k0,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_101[0], in.getSampleDataRO(INDEX3(k0+1,k1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2608                          const double* f_111 = in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1));                          memcpy(&f_111[0], in.getSampleDataRO(INDEX3(k0+1,k1+1,m_N2-1, m_N0,m_N1)), numComp*sizeof(double));
2609                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));                          double* o = out.getSampleDataRW(m_faceOffset[5]+INDEX2(k0,k1,m_NE0));
2610                          for (index_t i=0; i < numComp; ++i) {                          for (index_t i=0; i < numComp; ++i) {
2611                              o[INDEX2(i,numComp,0)] = f_001[i]*c2 + f_111[i]*c0 + c1*(f_011[i] + f_101[i]);                              o[INDEX2(i,numComp,0)] = f_001[i]*c2 + f_111[i]*c0 + c1*(f_011[i] + f_101[i]);

Legend:
Removed from v.3796  
changed lines
  Added in v.4154

  ViewVC Help
Powered by ViewVC 1.1.26