Bläddra i källkod

Boundary specification now coded

master
Trevor Irons 6 år sedan
förälder
incheckning
6facccdd37
7 ändrade filer med 379 tillägg och 134 borttagningar
  1. 11
    10
      CMakeLists.txt
  2. 0
    1
      config/EMSchur3DConfig.h.in
  3. 1
    0
      examples/CMakeLists.txt
  4. 156
    0
      examples/block.py
  5. 13
    5
      include/EMSchur3D.h
  6. 21
    1
      include/EMSchur3DBase.h
  7. 177
    117
      src/EMSchur3DBase.cpp

+ 11
- 10
CMakeLists.txt Visa fil

@@ -63,16 +63,17 @@ if ( LEMMA_VTK6_SUPPORT OR LEMMA_VTK7_SUPPORT OR LEMMA_VTK8_SUPPORT AND LEMMA_MO
63 63
 
64 64
 	# Linking
65 65
 	target_link_libraries(emschur3d ${VTK_LIBRARIES})
66
-if ( SUPERLU_FOUND )
67
-	target_link_libraries(emschur3d ${SUPERLU_LIBRARIES})
68
-endif()
69
-if ( PASTIX_FOUND )
70
-	target_link_libraries(emschur3d ${PASTIX_LIBRARIES})
71
-	target_link_libraries(emschur3d "blas" "metis" "scotch" "scotchmetis" "scotcherr" "scotcherrexit" "hwloc")
72
-endif()
73
-if ( UMFPACK_FOUND )
74
-	target_link_libraries(emschur3d ${UMFPACK_LIBRARIES})
75
-endif()
66
+
67
+	if ( SUPERLU_FOUND )
68
+		target_link_libraries(emschur3d ${SUPERLU_LIBRARIES})
69
+	endif()
70
+	if ( PASTIX_FOUND )
71
+		target_link_libraries(emschur3d ${PASTIX_LIBRARIES})
72
+		target_link_libraries(emschur3d "blas" "metis" "scotch" "scotchmetis" "scotcherr" "scotcherrexit" "hwloc")
73
+	endif()
74
+	if ( UMFPACK_FOUND )
75
+		target_link_libraries(emschur3d ${UMFPACK_LIBRARIES})
76
+	endif()
76 77
 
77 78
 	# Testing
78 79
 	if (LEMMA_ENABLE_TESTING)

+ 0
- 1
config/EMSchur3DConfig.h.in Visa fil

@@ -10,7 +10,6 @@
10 10
 /**
11 11
  * @file
12 12
  * @date      01/08/2018 04:01:30 PM
13
- * @version   $Id$
14 13
  * @author    Trevor Irons (ti)
15 14
  * @email     tirons@egi.utah.edu
16 15
  * @copyright Copyright (c) 2018, University of Utah

+ 1
- 0
examples/CMakeLists.txt Visa fil

@@ -15,6 +15,7 @@ install ( DIRECTORY mod  DESTINATION ${CMAKE_INSTALL_PREFIX}/share/EMSchur3D/ )
15 15
 install ( DIRECTORY grd  DESTINATION ${CMAKE_INSTALL_PREFIX}/share/EMSchur3D/ ) 
16 16
 install ( DIRECTORY src  DESTINATION ${CMAKE_INSTALL_PREFIX}/share/EMSchur3D/ ) 
17 17
 install ( FILES block.sh  DESTINATION ${CMAKE_INSTALL_PREFIX}/share/EMSchur3D/ ) 
18
+install ( FILES block.py  DESTINATION ${CMAKE_INSTALL_PREFIX}/share/EMSchur3D/ ) 
18 19
 
19 20
 INSTALL_TARGETS( "/share/EMSchur3D/"
20 21
     EMSchur3D

+ 156
- 0
examples/block.py Visa fil

@@ -0,0 +1,156 @@
1
+import numpy as np
2
+import pprint
3
+
4
+def calcH( oxx, nxx, dxx, pad ):
5
+    """Calculates grid spacing along a dimension, if padding cells are requested those are incorporated too"""
6
+    pp = 1.1 # fixed padding expansion factor 
7
+    if not pad:
8
+        px = np.arange(oxx-dxx/2, oxx-dxx/2+(nxx+1)*dxx, dxx)
9
+        hx = dxx*np.ones(nxx)
10
+        return hx, px 
11
+    else:
12
+        hx = np.zeros( nxx )
13
+        for ip in range(0,pad):
14
+            hx[ip] = dxx*pp**(pad-ip)      
15
+        hx[pad:nxx-pad] = dxx
16
+        ip = 1 
17
+        for ii in range (nxx-pad, nxx):
18
+            hx[ii] = dxx*pp**ip
19
+            ip += 1  
20
+
21
+        px = np.zeros( nxx + 1 )  # interfaces 
22
+        px[0] = oxx - (dxx*pp**pad)/2
23
+        for i, h in enumerate(hx):
24
+            px[i+1] = px[i]+h
25
+
26
+        return hx, px
27
+
28
+def writeH(fout, h, p):
29
+    ix = 0
30
+    rx,rxm1 = 0,0
31
+    while (ix < len(h)):
32
+        fout.write ("%6.2f" %( h[ix]) )
33
+        ix += 1
34
+        rx += 1 
35
+        if rx > 4:
36
+            fout.write(" //") # [%i:%i]\n" %(rxm1,ix-1))
37
+            #fout.write( (p[rxm1:ix-1]) )
38
+            for pp in p[rxm1:ix+1]:
39
+                fout.write(" %6.2f" %(pp))
40
+            fout.write("\n")
41
+            rxm1 += rx
42
+            rx = 0
43
+        else: 
44
+            fout.write(" ")
45
+
46
+def writeGRD(fout, args):
47
+    
48
+    fout.write( "%i\t%i\t%i\t// nx ny nz\n" %(args.nx[0],args.ny[0],args.nz[0]) )
49
+    fout.write( "%f\t%f\t%f\t// ox oy oz\n" %(args.ox[0],args.oy[0],args.oz[0]) )
50
+
51
+    fout.write("\n// hx\n")
52
+    hx,px = calcH( args.ox[0], args.nx[0], args.dx[0], args.pad )
53
+    writeH(fout, hx, px)
54
+    
55
+    fout.write("\n// hy\n")
56
+    hy,py = calcH( args.oy[0], args.ny[0], args.dy[0], args.pad )
57
+    writeH(fout, hy, py)
58
+    
59
+    fout.write("\n// hz\n")
60
+    hz,pz = calcH( args.oz[0], args.nz[0], args.dz[0], args.pad )
61
+    writeH(fout, hz, pz)
62
+
63
+    fout.write("\n\n")
64
+    #fout.write( "// vim: set tabstop=4 expandtab:\n")
65
+    fout.write( "// vim: set filetype=cpp:\n")
66
+
67
+    return px,py,pz
68
+
69
+def writeMOD(fout, args, px, py, pz):
70
+    sigma = np.zeros( (args.nx[0], args.ny[0], args.nz[0]) )  
71
+    sigma[:,:,pz[1:]>0] = 0.05
72
+    xlo = np.where( px[0:-1] >= args.bxlo[0] )[0][0] 
73
+    xhi = np.where( px[1:] <= args.bxhi[0] )[0][-1] + 1
74
+    ylo = np.where( py[0:-1] >= args.bylo[0] )[0][0] 
75
+    yhi = np.where( py[1:] <= args.byhi[0] )[0][-1] + 1
76
+    zlo = np.where( pz[0:-1] >= args.bzlo[0] )[0][0] 
77
+    zhi = np.where( pz[1:] <= args.bzhi[0] )[0][-1] + 1
78
+    sigma[xlo:xhi, ylo:yhi, zlo:zhi] = .1
79
+    for val in np.ravel(sigma, order='C'):
80
+        fout.write("%f\n" %(val) )
81
+
82
+def str2bool(v):
83
+    if v.lower() in ('yes', 'true', 't', 'y', '1'):
84
+        return True
85
+    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
86
+        return False
87
+    else:
88
+        raise argparse.ArgumentTypeError('Boolean value expected.')
89
+ 
90
+import argparse
91
+
92
+PAD = 0
93
+
94
+parser = argparse.ArgumentParser(description='Set up test EMSchur3D block problem.')
95
+
96
+parser.add_argument('nx', metavar='nx', type=int, nargs=1, 
97
+                   help='number of cells in x')
98
+
99
+parser.add_argument('ny', metavar='ny', type=int, nargs=1, 
100
+                   help='number of cells in y')
101
+
102
+parser.add_argument('nz', metavar='nz', type=int, nargs=1, 
103
+                   help='number of cells in z')
104
+
105
+parser.add_argument('ox', metavar='ox', type=float, nargs=1, 
106
+                   help='offset of grid in x')
107
+
108
+parser.add_argument('oy', metavar='oy', type=float, nargs=1, 
109
+                   help='offset of grid in y')
110
+
111
+parser.add_argument('oz', metavar='oz', type=float, nargs=1, 
112
+                   help='offset of grid in z')
113
+
114
+parser.add_argument('dx', metavar='dx', type=int, nargs=1, 
115
+                   help='minimum spacing in x')
116
+
117
+parser.add_argument('dy', metavar='dy', type=int, nargs=1, 
118
+                   help='minimum spacing in y')
119
+
120
+parser.add_argument('dz', metavar='dz', type=int, nargs=1, 
121
+                   help='minimum spacing in z')
122
+
123
+parser.add_argument('bxlo', metavar='bxlo', type=float, nargs=1, 
124
+                   help='low end of block cell location in x')
125
+
126
+parser.add_argument('bxhi', metavar='bxhi', type=float, nargs=1, 
127
+                   help='high end of block cell location in x')
128
+
129
+parser.add_argument('bylo', metavar='bylo', type=float, nargs=1, 
130
+                   help='low end of block cell location in y')
131
+
132
+parser.add_argument('byhi', metavar='byhi', type=float, nargs=1, 
133
+                   help='high end of block cell location in y')
134
+
135
+parser.add_argument('bzlo', metavar='bzlo', type=float, nargs=1, 
136
+                   help='low end of block cell location in z')
137
+
138
+parser.add_argument('bzhi', metavar='bzhi', type=float, nargs=1, 
139
+                   help='high end of block cell location in z')
140
+
141
+parser.add_argument("--pad", type=int, nargs='?',
142
+                        const=True, default=PAD, 
143
+                        help="Activate this number of padding cells with 10%% growth factor.")
144
+
145
+args = parser.parse_args()
146
+
147
+fout = open("example.grd", 'w')
148
+px,py,pz = writeGRD(fout, args)
149
+fout.close()
150
+
151
+mout = open("example.mod", 'w')
152
+writeMOD(mout, args, px, py, pz)
153
+
154
+#print(args.nx)
155
+#print(args.accumulate(args.nx))
156
+#print(args.accumulate(args.ny))

+ 13
- 5
include/EMSchur3D.h Visa fil

@@ -248,6 +248,8 @@ namespace Lemma {
248 248
 
249 249
         VectorXcr ADiv = D*A;  // ADiv == RHS == D C^I Se
250 250
         //VectorXcr Error = ((Cc.selfadjointView<Eigen::Lower>()*A).array() - Se.array());
251
+        VectorXcr Error = ((Cvec[iw]*A).array() - Se.array());
252
+/*
251 253
 #if LOWER==1
252 254
         std::cout << "Using Eigen::Lower to calculate Error" << std::endl;
253 255
         VectorXcr Error = ((Cvec[iw].selfadjointView<Eigen::Lower>()*A).array() - Se.array());
@@ -255,6 +257,7 @@ namespace Lemma {
255 257
         std::cout << "Using Eigen::Upper to calculate Error" << std::endl;
256 258
         VectorXcr Error = ((Cvec[iw].selfadjointView<Eigen::Upper>()*A).array() - Se.array());
257 259
 #endif
260
+*/
258 261
         logio << "|| Div(A) || = " << ADiv.norm()
259 262
               << "\tInital solution error="<<   Error.norm()  // Iteritive info
260 263
 //              << "\tSolver reported error="<<   CSolver[iw].error()  // Iteritive info
@@ -269,7 +272,7 @@ namespace Lemma {
269 272
         // Solve for Phi
270 273
         logio << "Solving for Phi " << std::flush;
271 274
         timer.begin();
272
-        tol = 1e-20;
275
+        tol = 1e-30;
273 276
         int success(2);
274 277
 
275 278
         success = implicitbicgstab(D, idx, ms, ADiv, Phi, CSolver[iw], max_it, tol, errorn, iter_done, logio);
@@ -313,6 +316,7 @@ namespace Lemma {
313 316
 
314 317
         // Report error of solutions
315 318
         //Error = ((Cc.selfadjointView<Eigen::Lower>()*A).array() + E.array() - Se.array());
319
+/*
316 320
 #if LOWER==1
317 321
         std::cout << "Using Eigen::Lower to calculate Error" << std::endl;
318 322
         Error = ((Cvec[iw].selfadjointView<Eigen::Lower>()*A).array() + E.array() - Se.array());
@@ -320,6 +324,8 @@ namespace Lemma {
320 324
         std::cout << "Using Eigen::Upper to calculate Error" << std::endl;
321 325
         Error = ((Cvec[iw].selfadjointView<Eigen::Upper>()*A).array() + E.array() - Se.array());
322 326
 #endif
327
+*/
328
+        Error = ((Cvec[iw]*A).array() + E.array() - Se.array());
323 329
         //      << "\tSolver reported error="<<   CSolver[iw].error()  // Iteritive info
324 330
         //      << "\ttime " << timer.end() / 60. << " [m]   "
325 331
         //      <<  CSolver[iw].iterations() << "  iterations"
@@ -432,22 +438,24 @@ namespace Lemma {
432 438
             jsw_timer timer;
433 439
             timer.begin();
434 440
 
435
-            CSolver[iw].isSymmetric(true);
441
+            //CSolver[iw].isSymmetric(true);
436 442
             //CSolver[iw].setPivotThreshold(0.0); // OK for symmetric complex systems with real and imaginary positive definite parts.
437
-            //                                  // but our imaginary part is negative definite
443
+            //                                    // but our imaginary part is negative definite
438 444
             //http://www.ams.org/journals/mcom/1998-67-224/S0025-5718-98-00978-8/S0025-5718-98-00978-8.pdf
439 445
 
440 446
             /*  Complex system */
441 447
             std::cout << "SparseLU pattern analyzing C_" << iw << ",";
442 448
             std::cout.flush();
443
-            CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
449
+            //CSolver[iw].analyzePattern( Cvec[iw].selfadjointView< Eigen::Lower>() );
450
+            CSolver[iw].analyzePattern( Cvec[iw] );
444 451
             std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
445 452
 
446 453
             // factorize
447 454
             timer.begin();
448 455
             std::cout << "SparseLU factorising C_" << iw << ", ";
449 456
             std::cout.flush();
450
-            CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
457
+            //CSolver[iw].factorize( Cvec[iw].selfadjointView< Eigen::Lower>() );
458
+            CSolver[iw].factorize( Cvec[iw] ); //.selfadjointView< Eigen::Lower>() );
451 459
             std::cout << " done in " << timer.end() / 60. << " [m]" << std::endl;
452 460
         }
453 461
     }

+ 21
- 1
include/EMSchur3DBase.h Visa fil

@@ -77,7 +77,8 @@
77 77
 
78 78
 namespace Lemma {
79 79
 
80
-#define UPPER 0  // LOWER WAS 0
80
+// Pardiso likes LOWER for Sym problem
81
+#define UPPER 1  // LOWER WAS 0
81 82
 #define LOWER 1  // 1=true, 0=false
82 83
 
83 84
 enum SOLVER{ SPARSELU, SimplicialLLT, SimplicialLDLT, BiCGStab, SparseQR };
@@ -434,6 +435,25 @@ class EMSchur3DBase : public LemmaObject {
434 435
     /** Marker for air cells */
435 436
     std::vector<int> idx;
436 437
 
438
+    /** Dirichlet on low X */
439
+    bool DirichletXLO = true;
440
+    //bool DirichletXLO = false;
441
+
442
+    bool DirichletXHI = true;
443
+    //bool DirichletXHI = false;
444
+
445
+    bool DirichletYLO = true;
446
+    //bool DirichletYLO = false;
447
+
448
+    bool DirichletYHI = true;
449
+    //bool DirichletYHI = false;
450
+
451
+//    bool DirichletZLO = true;
452
+    bool DirichletZLO = false;
453
+
454
+    bool DirichletZHI = true;
455
+//    bool DirichletZHI = false;
456
+
437 457
     private:
438 458
 
439 459
         static constexpr auto CName = "EMSchur3DBase";

+ 177
- 117
src/EMSchur3DBase.cpp Visa fil

@@ -9,7 +9,7 @@
9 9
 //
10 10
 //   Organisation:  University of Utah
11 11
 //
12
-//          Email:  tirons@egi.utah.edu
12
+//          Email:  Trevor.Irons@utah.edu
13 13
 //
14 14
 // ===========================================================================
15 15
 
@@ -17,8 +17,6 @@
17 17
   @file
18 18
   @author   Trevor Irons
19 19
   @date     09/20/2013
20
-  @version  $Id$
21
-  THis is a port of the procedural code developed at School of Mines
22 20
  **/
23 21
 
24 22
 #include "EMSchur3DBase.h"
@@ -26,10 +24,13 @@
26 24
 typedef Eigen::Triplet<Lemma::Complex> Tc;
27 25
 typedef Eigen::Triplet<Lemma::Real> Tr;
28 26
 
29
-// Moved to header 
27
+// Moved to header
30 28
 //#define UPPER 0  // LOWER WAS 0
31 29
 //#define LOWER 1  // 1=true, 0=false
32 30
 
31
+//#define FINITEVOLUME 1
32
+#define FINITEDIFFERENCE 1
33
+
33 34
 namespace Lemma {
34 35
 
35 36
 
@@ -137,31 +138,34 @@ namespace Lemma {
137 138
         for (int ix=0; ix<nx+1; ++ix) {
138 139
 
139 140
             // Calculate 1/2 step values on staggered grid
140
-            Real alo_ihz2(0);
141
-            Real ahi_ihz2(0);
141
+            Real hzlo(0);
142
+            Real hzhi(0);
142 143
             if (iz == 0) {
143
-                ahi_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
144
-                alo_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
144
+                hzlo = .5*hz[iz+1] + .5*hz[iz];                   // assume same grid spacing for boundary
145
+                hzhi = .5*hz[iz+1] + .5*hz[iz];
145 146
             } else if (iz == nz-1) {
146
-                alo_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
147
-                ahi_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
147
+                hzlo = .5*hz[iz-1] + .5*hz[iz];
148
+                hzhi = .5*hz[iz-1] + .5*hz[iz];                   // assume same grid spacing for boundary
148 149
             } else {
149
-                alo_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
150
-                ahi_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
150
+                hzlo = .5*hz[iz-1] + .5*hz[iz  ];
151
+                hzhi = .5*hz[iz  ] + .5*hz[iz+1];
151 152
             }
153
+            Real scz = 2./(hzlo+hzhi);
152 154
 
153
-            Real alo_ihy2(0);  // half step low jump in y
154
-            Real ahi_ihy2(0);  // half step high jump in y
155
+            // Calculate 1/2 step values on staggered grid
156
+            Real hylo(0);
157
+            Real hyhi(0);
155 158
             if (iy == 0) {
156
-                ahi_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
157
-                alo_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
159
+                hylo = .5*hy[iy+1] + .5*hy[iy];                   // assume same grid spacing for boundary
160
+                hyhi = .5*hy[iy+1] + .5*hy[iy];
158 161
             } else if (iy == ny-1) {
159
-                alo_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
160
-                ahi_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
162
+                hylo = .5*hy[iy-1] + .5*hy[iy];
163
+                hyhi = .5*hy[iy-1] + .5*hy[iy];                   // assume same grid spacing for boundary
161 164
             } else {
162
-                alo_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
163
-                ahi_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
165
+                hylo = .5*hy[iy-1] + .5*hy[iy  ];
166
+                hyhi = .5*hy[iy  ] + .5*hy[iy+1];
164 167
             }
168
+            Real scy = 2./(hylo+hyhi);
165 169
 
166 170
             /////////////////////////////////////////////////////////////////////////
167 171
             // Diagonal entry
@@ -179,31 +183,41 @@ namespace Lemma {
179 183
             //hsig += Complex(0, omega*EPSILON0);
180 184
 
181 185
             Real Sum(0);
182
-            if (ix == 0) {
183
-                // Dirichlet bdry condition on A
184
-                // Sum = alo_ihy2+ahi_ihy2 + alo_ihz2+ahi_ihz2 + 2.*ihx2[ix  ];
185
-                // Neumann bdry
186
-                Sum = alo_ihy2+ahi_ihy2 + alo_ihz2+ahi_ihz2 + ihx2[ix  ];
187
-            } else if (ix == nx) {
188
-                // Dirichlet bdry condition on A
189
-                // Sum = alo_ihy2+ahi_ihy2 + alo_ihz2+ahi_ihz2 + 2.*ihx2[ix-1];
190
-                // Neumann bdry
191
-                Sum = alo_ihy2+ahi_ihy2 + alo_ihz2+ahi_ihz2 + ihx2[ix-1];
186
+            Real scx(0);
187
+            if (ix == 0) { // x- bdry
188
+                scx = 2./(hx[ix]+hx[ix]);
189
+                if (DirichletXLO) {
190
+                    /* Dirichlet bdry condition on A */
191
+                    Sum = scz/hzlo + scz/hzhi + scy/hylo + scy/hyhi + 2.*scx/hx[ix];
192
+                } else {
193
+                    /* Neumann bdry */
194
+                    Sum = scz/hzlo + scz/hzhi + scy/hylo + scy/hyhi + scx/hx[ix];
195
+                }
196
+            } else if (ix == nx) {  // x+ bdry
197
+                scx = 2./(hx[ix-1]+hx[ix-1]);
198
+                if (DirichletXHI) {
199
+                    /* Dirichlet bdry condition on A */
200
+                    Sum = scz/hzlo + scz/hzhi + scy/hylo + scy/hyhi + 2.*scx/hx[ix-1];
201
+                } else {
202
+                    /* Neumann bdry */
203
+                    Sum = scz/hzlo + scz/hzhi + scy/hylo + scy/hyhi + scx/hx[ix-1];
204
+                }
192 205
             } else {
193
-                Sum = alo_ihy2+ahi_ihy2 + alo_ihz2+ahi_ihz2 + ihx2[ix] + ihx2[ix-1];
206
+                scx = 2./(hx[ix]+hx[ix-1]);
207
+                Sum = scz/hzlo + scz/hzhi + scy/hylo + scy/hyhi + scx/hx[ix] + scx/hx[ix-1];
194 208
             }
195 209
 
196 210
             /////////////////////////////////////////
197 211
             // minus side off diagonal terms
198 212
 #if LOWER
199 213
             // Third Off Diagonal
200
-            if (iz!=0)         Cvec[iw].insert(ir, ic-ny*(nx+1)) = Complex(-ahi_ihz2, 0);
214
+            if (iz!=0)         Cvec[iw].insert(ir, ic-ny*(nx+1)) = Complex(-scz/hzlo, 0);
201 215
 
202 216
             // Second Off Diagonal
203
-            if (iy!=0)         Cvec[iw].insert(ir, ic-(nx+1)) = Complex(-ahi_ihy2, 0);
217
+            if (iy!=0)         Cvec[iw].insert(ir, ic-(nx+1)) = Complex(-scy/hylo, 0);
204 218
 
205 219
             // First  Off Diagonal
206
-            if (ix!=0)         Cvec[iw].insert(ir, ic-1) = Complex(-ihx2[ix-1], 0);
220
+            if (ix!=0)         Cvec[iw].insert(ir, ic-1) = Complex(-scx/hx[ix-1], 0);
207 221
 #endif
208 222
             ////////////////////////////////////////////
209 223
             // Diagonal Term
@@ -215,13 +229,13 @@ namespace Lemma {
215 229
             // plus side off diagonal terms
216 230
 #if UPPER
217 231
             // First Off Diagonal
218
-            if (ix!=nx)         Cvec[iw].insert(ir, ic+1) = Complex(-ihx2[ix], 0);
232
+            if (ix!=nx)         Cvec[iw].insert(ir, ic+1) = Complex(-scx/hx[ix], 0);
219 233
 
220 234
             // Second Off Diagonal
221
-            if (iy!=ny-1)       Cvec[iw].insert(ir, ic+(nx+1)) = Complex(-ahi_ihy2, 0);
235
+            if (iy!=ny-1)       Cvec[iw].insert(ir, ic+(nx+1)) = Complex(-scy/hyhi, 0);
222 236
 
223 237
             // Third Off Diagonal
224
-            if (iz!=nz-1)       Cvec[iw].insert(ir, ic+ny*(nx+1)) = Complex(-ahi_ihz2, 0);
238
+            if (iz!=nz-1)       Cvec[iw].insert(ir, ic+ny*(nx+1)) = Complex(-scz/hzhi, 0);
225 239
 #endif
226 240
             ++ir;
227 241
             ++ic;
@@ -236,32 +250,34 @@ namespace Lemma {
236 250
         for (int ix=0; ix<nx;   ++ix) {
237 251
 
238 252
             // Calculate 1/2 step values on staggered grid
239
-            Real alo_ihz2(0);
240
-            Real ahi_ihz2(0);
241
-            if (iz == 0) {
242
-                ahi_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
243
-                alo_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
244
-            } else if (iz == nz-1) {
245
-                alo_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
246
-                ahi_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
253
+            Real hxlo(0);
254
+            Real hxhi(0);
255
+            if (ix == 0) {
256
+                hxlo = .5*hx[ix+1] + .5*hx[ix];                   // assume same grid spacing for boundary
257
+                hxhi = .5*hx[ix+1] + .5*hx[ix];
258
+            } else if (ix == nx-1) {
259
+                hxlo = .5*hx[ix-1] + .5*hx[ix];
260
+                hxhi = .5*hx[ix-1] + .5*hx[ix];                   // assume same grid spacing for boundary
247 261
             } else {
248
-                alo_ihz2 = std::pow(.5*hz[iz-1] + .5*hz[iz], -2);
249
-                ahi_ihz2 = std::pow(.5*hz[iz+1] + .5*hz[iz], -2);
262
+                hxlo = .5*hx[ix-1] + .5*hx[ix  ];
263
+                hxhi = .5*hx[ix  ] + .5*hx[ix+1];
250 264
             }
265
+            Real scx = 2./(hxlo+hxhi);
251 266
 
252 267
             // Calculate 1/2 step values on staggered grid
253
-            Real alo_ihx2(0);
254
-            Real ahi_ihx2(0);
255
-            if (ix == 0) {
256
-                ahi_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
257
-                alo_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
258
-            } else if (ix == nx-1) {
259
-                alo_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
260
-                ahi_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
268
+            Real hzlo(0);
269
+            Real hzhi(0);
270
+            if (iz == 0) {
271
+                hzlo = .5*hz[iz+1] + .5*hz[iz];                   // assume same grid spacing for boundary
272
+                hzhi = .5*hz[iz+1] + .5*hz[iz];
273
+            } else if (iz == nz-1) {
274
+                hzlo = .5*hz[iz-1] + .5*hz[iz];
275
+                hzhi = .5*hz[iz-1] + .5*hz[iz];                   // assume same grid spacing for boundary
261 276
             } else {
262
-                alo_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
263
-                ahi_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
277
+                hzlo = .5*hz[iz-1] + .5*hz[iz  ];
278
+                hzhi = .5*hz[iz  ] + .5*hz[iz+1];
264 279
             }
280
+            Real scz = 2./(hzlo+hzhi);
265 281
 
266 282
             // Harmonically average sigmay
267 283
             if (iy == 0) {
@@ -277,28 +293,38 @@ namespace Lemma {
277 293
             //hsig += Complex(0, omega*EPSILON0);
278 294
 
279 295
             Real Sum(0);
280
-            if (iy == 0) {
281
-                // Dirichlet bdry condition on A
282
-                //Sum = alo_ihx2+ahi_ihx2 + alo_ihz2+ahi_ihz2 + 2.*ihy2[iy  ];
283
-                // Neumann bdry
284
-                Sum = alo_ihx2+ahi_ihx2 + alo_ihz2+ahi_ihz2 + ihy2[iy  ];
285
-            } else if (iy == ny) {
286
-                // Dirichlet bdry condition on A
287
-                //Sum = alo_ihx2+ahi_ihx2 + alo_ihz2+ahi_ihz2 + 2.*ihy2[iy-1];
288
-                // Neumann bdry
289
-                Sum = alo_ihx2+ahi_ihx2 + alo_ihz2+ahi_ihz2 + ihy2[iy-1];
296
+            Real scy(0);
297
+            if (iy == 0) {  // y- bdry
298
+                scy = 2./(hy[iy]+hy[iy]);
299
+                if (DirichletYLO) {
300
+                    /* Dirichlet bdry condition on A */
301
+                    Sum = scz/hzlo + scz/hzhi + scx/hxlo + scx/hxhi + 2.*scy/hy[iy];
302
+                } else {
303
+                    /* Neumann bdry */
304
+                    Sum = scz/hzlo + scz/hzhi + scx/hxlo + scx/hxhi + scy/hy[iy];
305
+                }
306
+            } else if (iy == ny) {  // y+ bdry
307
+                scy = 2./(hy[iy-1]+hy[iy-1]);
308
+                if (DirichletYHI) {
309
+                    /* Dirichlet bdry condition on A */
310
+                    Sum = scz/hzlo + scz/hzhi + scx/hxlo + scx/hxhi + 2.*scy/hy[iy-1];
311
+                } else {
312
+                    /* Neumann bdry */
313
+                    Sum = scz/hzlo + scz/hzhi + scx/hxlo + scx/hxhi + scy/hy[iy-1];
314
+                }
290 315
             } else {
291
-                Sum = alo_ihx2+ahi_ihx2 + alo_ihz2+ahi_ihz2 + ihy2[iy] + ihy2[iy-1];
316
+                scy = 2./(hy[iy]+hy[iy-1]);
317
+                Sum = scz/hzlo + scz/hzhi + scx/hxlo + scx/hxhi + scy/hy[iy-1] + scy/hy[iy];
292 318
             }
293 319
 #if LOWER
294 320
             // Third Off Diagonal
295
-            if (iz!=0)              Cvec[iw].insert(ir,ic-(ny+1)*(nx)) = Complex(-ahi_ihz2, 0);
321
+            if (iz!=0)              Cvec[iw].insert(ir,ic-(ny+1)*(nx)) = Complex(-scz/hzlo, 0);
296 322
 
297 323
             // Second Off Diagonal
298
-            if (iy!=0)              Cvec[iw].insert(ir,ic-(nx)) = Complex(-ihy2[iy-1], 0);
324
+            if (iy!=0)              Cvec[iw].insert(ir,ic-(nx)) = Complex(-scy/hy[iy-1], 0);
299 325
 
300 326
             // First Off Diagonal
301
-            if (ix!=0)              Cvec[iw].insert(ir,ic-1) = Complex(-ahi_ihx2, 0);
327
+            if (ix!=0)              Cvec[iw].insert(ir,ic-1) = Complex(-scx/hxlo, 0);
302 328
 #endif
303 329
             // Diagonal Term
304 330
             Cvec[iw].insert(ir,ic) =       Complex(Sum, 0) + Complex(0,1)*omega*MU0*hsig;
@@ -306,13 +332,13 @@ namespace Lemma {
306 332
             //CMMvec[iw].insert(ir,ic) =  1./ Complex(Sum, omega*MU0*hsig);
307 333
 #if UPPER
308 334
             // First Off Diagonal
309
-            if (ix!=nx-1)           Cvec[iw].insert(ir,ic+1) = Complex(-ahi_ihx2, 0);
335
+            if (ix!=nx-1)           Cvec[iw].insert(ir,ic+1) = Complex(-scx/hxhi, 0);
310 336
 
311 337
             // Second Off Diagonal
312
-            if (iy!=ny)             Cvec[iw].insert(ir,ic+(nx)) = Complex(-ihy2[iy], 0);
338
+            if (iy!=ny)             Cvec[iw].insert(ir,ic+(nx)) = Complex(-scy/hy[iy], 0);
313 339
 
314 340
             // Third Off Diagonal
315
-            if (iz!=nz-1)           Cvec[iw].insert(ir,ic+(ny+1)*(nx)) = Complex(-ahi_ihz2, 0);
341
+            if (iz!=nz-1)           Cvec[iw].insert(ir,ic+(ny+1)*(nx)) = Complex(-scz/hzhi, 0);
316 342
 #endif
317 343
             ++ir;
318 344
             ++ic;
@@ -327,32 +353,34 @@ namespace Lemma {
327 353
         for (int ix=0; ix<nx;   ++ix) {
328 354
 
329 355
             // Calculate 1/2 step values on staggered grid
330
-            Real alo_ihx2(0);
331
-            Real ahi_ihx2(0);
332
-            if (ix == 0) {
333
-                ahi_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
334
-                alo_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
335
-            } else if (ix == nx-1) {
336
-                alo_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
337
-                ahi_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
356
+            Real hylo(0);
357
+            Real hyhi(0);
358
+            if (iy == 0) {
359
+                hylo = .5*hy[iy+1] + .5*hy[iy];                   // assume same grid spacing for boundary
360
+                hyhi = .5*hy[iy+1] + .5*hy[iy];
361
+            } else if (iy == ny-1) {
362
+                hylo = .5*hy[iy-1] + .5*hy[iy];
363
+                hyhi = .5*hy[iy-1] + .5*hy[iy];                   // assume same grid spacing for boundary
338 364
             } else {
339
-                alo_ihx2 = std::pow(.5*hx[ix-1] + .5*hx[ix], -2);
340
-                ahi_ihx2 = std::pow(.5*hx[ix+1] + .5*hx[ix], -2);
365
+                hylo = .5*hy[iy-1] + .5*hy[iy  ];
366
+                hyhi = .5*hy[iy  ] + .5*hy[iy+1];
341 367
             }
368
+            Real scy = 2./(hylo+hyhi);
342 369
 
343 370
             // Calculate 1/2 step values on staggered grid
344
-            Real alo_ihy2(0);
345
-            Real ahi_ihy2(0);
346
-            if (iy == 0) {
347
-                ahi_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
348
-                alo_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
349
-            } else if (iy == ny-1) {
350
-                alo_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
351
-                ahi_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
371
+            Real hxlo(0);
372
+            Real hxhi(0);
373
+            if (ix == 0) {
374
+                hxlo = .5*hx[ix+1] + .5*hx[ix];                   // assume same grid spacing for boundary
375
+                hxhi = .5*hx[ix+1] + .5*hx[ix];
376
+            } else if (ix == nx-1) {
377
+                hxlo = .5*hx[ix-1] + .5*hx[ix];
378
+                hxhi = .5*hx[ix-1] + .5*hx[ix];                   // assume same grid spacing for boundary
352 379
             } else {
353
-                alo_ihy2 = std::pow(.5*hy[iy-1] + .5*hy[iy], -2);
354
-                ahi_ihy2 = std::pow(.5*hy[iy+1] + .5*hy[iy], -2);
380
+                hxlo = .5*hx[ix-1] + .5*hx[ix  ];
381
+                hxhi = .5*hx[ix  ] + .5*hx[ix+1];
355 382
             }
383
+            Real scx = 2./(hxlo+hxhi);
356 384
 
357 385
             // Harmonically average sigmaz
358 386
             if (iz==0) {
@@ -368,28 +396,39 @@ namespace Lemma {
368 396
             //hsig += Complex(0, omega*EPSILON0);
369 397
 
370 398
             Real Sum(0);
371
-            if (iz == 0) {
372
-                // Dirichlet bdry condition on A
373
-                //Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + 2.*ihz2[iz  ];
374
-                // Neumann bdry
375
-                Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + ihz2[iz  ];
376
-            } else if (iz == nz) {
377
-                // Dirichlet bdry condition on A
378
-                Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + 2.*ihz2[iz-1];
379
-                // Neumann bdry
380
-                //Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + ihz2[iz-1];
399
+            Real scz(0);
400
+            if (iz == 0) { // z- bdry
401
+                scz = 2./(hz[iz]+hz[iz]);
402
+                if (DirichletZLO) {
403
+                    /* Dirichlet bdry condition on A */
404
+                    Sum = scx/hxlo + scx/hxhi + scy/hylo + scy/hyhi + 2.*scz/hz[iz];
405
+                } else {
406
+                    // Neumann bdry
407
+                    Sum = scx/hxlo + scx/hxhi + scy/hylo + scy/hyhi + scz/hz[iz];
408
+                }
409
+            } else if (iz == nz) { // z+ bdry
410
+                scz = 2./(hz[iz-1]+hz[iz-1]);
411
+                if (DirichletZHI) {
412
+                    // Dirichlet bdry condition on A
413
+                    Sum = scx/hxlo + scx/hxhi + scy/hylo + scy/hyhi + 2.*scz/hz[iz-1];
414
+                } else {
415
+                    // Neumann bdry
416
+                    //Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + ihz2[iz-1];
417
+                    Sum = scx/hxlo + scx/hxhi + scy/hylo + scy/hyhi + scz/hz[iz-1];
418
+                }
381 419
             } else {
382
-                Sum = alo_ihx2 + ahi_ihx2 + alo_ihy2 + ahi_ihy2 + ihz2[iz] + ihz2[iz-1];
420
+                scz = 2./(hz[iz]+hz[iz-1]);
421
+                Sum = scx/hxlo + scx/hxhi + scy/hylo + scy/hyhi + scz/hz[iz-1] + scz/hz[iz];
383 422
             }
384 423
 #if LOWER
385 424
             // Third Off Diagonal
386
-            if (iz!=0)             Cvec[iw].insert(ir,ic-ny*(nx)) = Complex(-ihz2[iz-1], 0);
425
+            if (iz!=0)             Cvec[iw].insert(ir,ic-ny*(nx)) = Complex(-scz/hz[iz-1], 0);
387 426
 
388 427
             // Second Off Diagonal
389
-            if (iy!=0)           Cvec[iw].insert(ir,ic-(nx)) = Complex(-ahi_ihy2, 0);
428
+            if (iy!=0)           Cvec[iw].insert(ir,ic-(nx)) = Complex(-scy/hylo, 0);
390 429
 
391 430
             // First Off Diagonal
392
-            if (ix!=0)           Cvec[iw].insert(ir,ic-1) = Complex(-ahi_ihx2, 0);
431
+            if (ix!=0)           Cvec[iw].insert(ir,ic-1) = Complex(-scx/hxlo, 0);
393 432
 #endif
394 433
             // Diagonal Term
395 434
             Cvec[iw].insert(ir,ic) =       Complex(Sum, 0) + Complex(0,1)*omega*MU0*hsig;
@@ -397,13 +436,13 @@ namespace Lemma {
397 436
             //CMMvec[iw].insert(ir,ic) =  1. / Complex(Sum, omega*MU0*hsig);
398 437
 #if UPPER
399 438
             // First Off Diagonal
400
-            if (ix!=nx-1)           Cvec[iw].insert(ir,ic+1) = Complex(-ahi_ihx2, 0);
439
+            if (ix!=nx-1)           Cvec[iw].insert(ir,ic+1) = Complex(-scx/hx[ix], 0);
401 440
 
402 441
             // Second Off Diagonal
403
-            if (iy!=ny-1)           Cvec[iw].insert(ir,ic+(nx)) = Complex(-ahi_ihy2, 0);
442
+            if (iy!=ny-1)           Cvec[iw].insert(ir,ic+(nx)) = Complex(-scy/hy[iy], 0);
404 443
 
405 444
             // Third Off Diagonal
406
-            if (iz!=nz)             Cvec[iw].insert(ir,ic+ny*(nx)) = Complex(-ihz2[iz], 0);
445
+            if (iz!=nz)             Cvec[iw].insert(ir,ic+ny*(nx)) = Complex(-scz/hz[iz], 0);
407 446
 #endif
408 447
             ++ir;
409 448
             ++ic;
@@ -777,8 +816,15 @@ namespace Lemma {
777 816
             for (int ix=0; ix<nx; ++ix) {
778 817
                 //D.insert(ir, ic-1) = Complex(-ihx[ix], 0);
779 818
                 //D.insert(ir, ic  ) = Complex( ihx[ix], 0);
780
-                triplets.push_back( Tc(ir, ic-1, Complex(-ihx[ix], 0)) );
781
-                triplets.push_back( Tc(ir, ic  , Complex( ihx[ix], 0)) );
819
+#ifdef FINITEDIFFERENCE
820
+                //triplets.push_back( Tc(ir, ic-1, Complex(-sc*ihx[ix], 0)) );
821
+                //triplets.push_back( Tc(ir, ic  , Complex( sc*ihx[ix], 0)) );
822
+                triplets.push_back( Tc(ir, ic-1, Complex(-1.0/hx[ix], 0)) );
823
+                triplets.push_back( Tc(ir, ic  , Complex( 1.0/hx[ix], 0)) );
824
+#elif FINITEVOLUME
825
+                triplets.push_back( Tc(ir, ic-1, Complex(-1, 0)) );
826
+                triplets.push_back( Tc(ir, ic  , Complex( 1, 0)) );
827
+#endif
782 828
                 ++ir;
783 829
                 ++ic;
784 830
             }
@@ -794,8 +840,15 @@ namespace Lemma {
794 840
             for (int ix=0; ix<nx; ++ix) {
795 841
                 //D.insert(ir, ic   ) = Complex(-ihy[iy], 0);
796 842
                 //D.insert(ir, ic+nx) = Complex( ihy[iy], 0);
797
-                triplets.push_back( Tc(ir, ic   , Complex(-ihy[iy], 0)) );
798
-                triplets.push_back( Tc(ir, ic+nx, Complex( ihy[iy], 0)) );
843
+#ifdef FINITEDIFFERENCE
844
+                //triplets.push_back( Tc(ir, ic   , Complex(-sc*ihy[iy], 0)) );
845
+                //triplets.push_back( Tc(ir, ic+nx, Complex( sc*ihy[iy], 0)) );
846
+                triplets.push_back( Tc(ir, ic   , Complex(-1.0/hy[iy], 0)) );
847
+                triplets.push_back( Tc(ir, ic+nx, Complex( 1.0/hy[iy], 0)) );
848
+#elif FINITEVOLUME
849
+                triplets.push_back( Tc(ir, ic   , Complex(-1, 0)) );
850
+                triplets.push_back( Tc(ir, ic+nx, Complex( 1, 0)) );
851
+#endif
799 852
                 ++ir;
800 853
                 ++ic;
801 854
             }
@@ -812,8 +865,15 @@ namespace Lemma {
812 865
         for (int ix=0; ix<nx; ++ix) {
813 866
             //D.insert(ir, ic      ) = Complex(-ihz[iz], 0);
814 867
             //D.insert(ir, ic+nx*ny) = Complex( ihz[iz], 0);
815
-            triplets.push_back( Tc(ir, ic      , Complex(-ihz[iz], 0)) );
816
-            triplets.push_back( Tc(ir, ic+nx*ny, Complex( ihz[iz], 0)) );
868
+#ifdef FINITEDIFFERENCE
869
+            //triplets.push_back( Tc(ir, ic      , Complex(-sc*ihz[iz], 0)) );
870
+            //triplets.push_back( Tc(ir, ic+nx*ny, Complex( sc*ihz[iz], 0)) );
871
+            triplets.push_back( Tc(ir, ic      , Complex(-1.0/hz[iz], 0)) );
872
+            triplets.push_back( Tc(ir, ic+nx*ny, Complex( 1.0/hz[iz], 0)) );
873
+#elif FINITEVOLUME
874
+            triplets.push_back( Tc(ir, ic      , Complex(-1, 0)) );
875
+            triplets.push_back( Tc(ir, ic+nx*ny, Complex( 1, 0)) );
876
+#endif
817 877
             ++ir;
818 878
             ++ic;
819 879
         }

Laddar…
Avbryt
Spara