public void testUniformGridMesher() { int[] dims = new int[] { 5, 7, 8 }; List <int> dim = new List <int>(dims); FdmLinearOpLayout layout = new FdmLinearOpLayout(dim); List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > ();; boundaries.Add(new Pair <double?, double?>(-5, 10)); boundaries.Add(new Pair <double?, double?>(5, 100)); boundaries.Add(new Pair <double?, double?>(10, 20)); UniformGridMesher mesher = new UniformGridMesher(layout, boundaries); double dx1 = 15.0 / (dim[0] - 1); double dx2 = 95.0 / (dim[1] - 1); double dx3 = 10.0 / (dim[2] - 1); double tol = 100 * Const.QL_EPSILON; if (Math.Abs(dx1 - mesher.dminus(layout.begin(), 0).Value) > tol || Math.Abs(dx1 - mesher.dplus(layout.begin(), 0).Value) > tol || Math.Abs(dx2 - mesher.dminus(layout.begin(), 1).Value) > tol || Math.Abs(dx2 - mesher.dplus(layout.begin(), 1).Value) > tol || Math.Abs(dx3 - mesher.dminus(layout.begin(), 2).Value) > tol || Math.Abs(dx3 - mesher.dplus(layout.begin(), 2).Value) > tol) { QAssert.Fail("inconsistent uniform mesher object"); } }
public void testTripleBandMapSolve() { int[] dims = new int[] { 100, 400 }; List <int> dim = new List <int>(dims); FdmLinearOpLayout layout = new FdmLinearOpLayout(dim); List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > (); boundaries.Add(new Pair <double?, double?>(0, 1.0)); boundaries.Add(new Pair <double?, double?>(0, 1.0)); FdmMesher mesher = new UniformGridMesher(layout, boundaries); FirstDerivativeOp dy = new FirstDerivativeOp(1, mesher); dy.axpyb(new Vector(1, 2.0), dy, dy, new Vector(1, 1.0)); // check copy constructor FirstDerivativeOp copyOfDy = new FirstDerivativeOp(dy); Vector u = new Vector(layout.size()); for (int i = 0; i < layout.size(); ++i) { u[i] = Math.Sin(0.1 * i) + Math.Cos(0.35 * i); } Vector t = new Vector(dy.solve_splitting(copyOfDy.apply(u), 1.0, 0.0)); for (int i = 0; i < u.size(); ++i) { if (Math.Abs(u[i] - t[i]) > 1e-6) { QAssert.Fail("solve and apply are not consistent " + "\n expected : " + u[i] + "\n calculated : " + t[i]); } } FirstDerivativeOp dx = new FirstDerivativeOp(0, mesher); dx.axpyb(new Vector(), dx, dx, new Vector(1, 1.0)); FirstDerivativeOp copyOfDx = new FirstDerivativeOp(0, mesher); // check assignment copyOfDx = dx; t = dx.solve_splitting(copyOfDx.apply(u), 1.0, 0.0); for (int i = 0; i < u.size(); ++i) { if (Math.Abs(u[i] - t[i]) > 1e-6) { QAssert.Fail("solve and apply are not consistent " + "\n expected : " + u[i] + "\n calculated : " + t[i]); } } SecondDerivativeOp dxx = new SecondDerivativeOp(0, mesher); dxx.axpyb(new Vector(1, 0.5), dxx, dx, new Vector(1, 1.0)); // check of copy constructor SecondDerivativeOp copyOfDxx = new SecondDerivativeOp(dxx); t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0); for (int i = 0; i < u.size(); ++i) { if (Math.Abs(u[i] - t[i]) > 1e-6) { QAssert.Fail("solve and apply are not consistent " + "\n expected : " + u[i] + "\n calculated : " + t[i]); } } //check assignment operator copyOfDxx.add(new SecondDerivativeOp(1, mesher)); copyOfDxx = dxx; t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0); for (int i = 0; i < u.size(); ++i) { if (Math.Abs(u[i] - t[i]) > 1e-6) { QAssert.Fail("solve and apply are not consistent " + "\n expected : " + u[i] + "\n calculated : " + t[i]); } } }
public void testSecondOrderMixedDerivativesMapApply() { int[] dims = new int[] { 50, 50, 50 }; List <int> dim = new List <int>(dims); FdmLinearOpLayout index = new FdmLinearOpLayout(dim); List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > (); boundaries.Add(new Pair <double?, double?>(0, 0.5)); boundaries.Add(new Pair <double?, double?>(0, 0.5)); boundaries.Add(new Pair <double?, double?>(0, 0.5)); FdmMesher mesher = new UniformGridMesher(index, boundaries); Vector r = new Vector(mesher.layout().size()); FdmLinearOpIterator endIter = index.end(); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); r[iter.index()] = Math.Sin(x) * Math.Cos(y) * Math.Exp(z); } Vector t = new SecondOrderMixedDerivativeOp(0, 1, mesher).apply(r); Vector u = new SecondOrderMixedDerivativeOp(1, 0, mesher).apply(r); double tol = 5e-2; for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = -Math.Cos(x) * Math.Sin(y) * Math.Exp(z); if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dxdy deviation is too big" + "\n found at " + x + " " + y + " " + z); } if (Math.Abs(t[i] - u[i]) > 1e5 * Const.QL_EPSILON) { QAssert.Fail("numerical derivative in dxdy not equal to dydx" + "\n found at " + x + " " + y + " " + z + "\n value " + Math.Abs(t[i] - u[i])); } } t = new SecondOrderMixedDerivativeOp(0, 2, mesher).apply(r); u = new SecondOrderMixedDerivativeOp(2, 0, mesher).apply(r); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = Math.Cos(x) * Math.Cos(y) * Math.Exp(z); if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dxdy deviation is too big" + "\n found at " + x + " " + y + " " + z); } if (Math.Abs(t[i] - u[i]) > 1e5 * Const.QL_EPSILON) { QAssert.Fail("numerical derivative in dxdz not equal to dzdx" + "\n found at " + x + " " + y + " " + z + "\n value " + Math.Abs(t[i] - u[i])); } } t = new SecondOrderMixedDerivativeOp(1, 2, mesher).apply(r); u = new SecondOrderMixedDerivativeOp(2, 1, mesher).apply(r); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = -Math.Sin(x) * Math.Sin(y) * Math.Exp(z); if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dydz deviation is too big" + "\n found at " + x + " " + y + " " + z); } if (Math.Abs(t[i] - u[i]) > 1e5 * Const.QL_EPSILON) { QAssert.Fail("numerical derivative in dydz not equal to dzdy" + "\n found at " + x + " " + y + " " + z + "\n value " + Math.Abs(t[i] - u[i])); } } }
public void testSecondDerivativesMapApply() { int[] dims = new int[] { 50, 50, 50 }; List <int> dim = new List <int>(dims); FdmLinearOpLayout index = new FdmLinearOpLayout(dim); List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > (); boundaries.Add(new Pair <double?, double?>(0, 0.5)); boundaries.Add(new Pair <double?, double?>(0, 0.5)); boundaries.Add(new Pair <double?, double?>(0, 0.5)); FdmMesher mesher = new UniformGridMesher(index, boundaries); Vector r = new Vector(mesher.layout().size()); FdmLinearOpIterator endIter = index.end(); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); r[iter.index()] = Math.Sin(x) * Math.Cos(y) * Math.Exp(z); } Vector t = new SecondDerivativeOp(0, mesher).apply(r); double tol = 5e-2; for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = -Math.Sin(x) * Math.Cos(y) * Math.Exp(z); if (iter.coordinates()[0] == 0 || iter.coordinates()[0] == dims[0] - 1) { d = 0; } if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dx^2 deviation is too big" + "\n found at " + x + " " + y + " " + z); } } t = new SecondDerivativeOp(1, mesher).apply(r); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = -Math.Sin(x) * Math.Cos(y) * Math.Exp(z); if (iter.coordinates()[1] == 0 || iter.coordinates()[1] == dims[1] - 1) { d = 0; } if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dy^2 deviation is too big" + "\n found at " + x + " " + y + " " + z); } } t = new SecondDerivativeOp(2, mesher).apply(r); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int i = iter.index(); double x = mesher.location(iter, 0); double y = mesher.location(iter, 1); double z = mesher.location(iter, 2); double d = Math.Sin(x) * Math.Cos(y) * Math.Exp(z); if (iter.coordinates()[2] == 0 || iter.coordinates()[2] == dims[2] - 1) { d = 0; } if (Math.Abs(d - t[i]) > tol) { QAssert.Fail("numerical derivative in dz^2 deviation is too big" + "\n found at " + x + " " + y + " " + z); } } }
public void testFirstDerivativesMapApply() { int[] dims = new int[] { 400, 100, 50 }; List <int> dim = new List <int>(dims); FdmLinearOpLayout index = new FdmLinearOpLayout(dim); List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > (); boundaries.Add(new Pair <double?, double?>(-5, 5)); boundaries.Add(new Pair <double?, double?>(0, 10)); boundaries.Add(new Pair <double?, double?>(5, 15)); FdmMesher mesher = new UniformGridMesher(index, boundaries); FirstDerivativeOp map = new FirstDerivativeOp(2, mesher); Vector r = new Vector(mesher.layout().size()); FdmLinearOpIterator endIter = index.end(); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { r[iter.index()] = Math.Sin(mesher.location(iter, 0)) + Math.Cos(mesher.location(iter, 2)); } Vector t = map.apply(r); double dz = (boundaries[2].second.Value - boundaries[2].first.Value) / (dims[2] - 1); for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter) { int z = iter.coordinates()[2]; int z0 = (z > 0) ? z - 1 : 1; int z2 = (z < dims[2] - 1) ? z + 1 : dims[2] - 2; double lz0 = boundaries[2].first.Value + z0 * dz; double lz2 = boundaries[2].first.Value + z2 * dz; double expected; if (z == 0) { expected = (Math.Cos(boundaries[2].first.Value + dz) - Math.Cos(boundaries[2].first.Value)) / dz; } else if (z == dim[2] - 1) { expected = (Math.Cos(boundaries[2].second.Value) - Math.Cos(boundaries[2].second.Value - dz)) / dz; } else { expected = (Math.Cos(lz2) - Math.Cos(lz0)) / (2 * dz); } double calculated = t[iter.index()]; if (Math.Abs(calculated - expected) > 1e-10) { QAssert.Fail("first derivative calculation failed." + "\n calculated: " + calculated + "\n expected: " + expected); } } }