sgdae/0000755000175000017500000000000014744140042012063 5ustar msautermsautersgdae/config.custom0000644000175000017500000000043610754367672014610 0ustar msautermsauter# Set MKL variable to path of the Intel Math Kernel Library. # MKL := /opt/intel/mkl/x.y.zzz # DEFINES += -DMKL # Add flags to the variables INCLUDES, LDFLAGS, LDLIBS to support linking with any additional libraries. # Add flags to the variables DEFINES, OPTIMIZE for a custom build. sgdae/problems.hxx0000644000175000017500000036156510754367672014500 0ustar msautermsauter/* This file is part of SGDAE, a software to numerically solve differential algebraic equations using a steepest descent method based on Sobolev gradients. You are welcome to contact the authors via e-mail: Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __PROBLEMS_HXX__ #define __PROBLEMS_HXX__ namespace problems { using boost::assign::init; struct problem_linear {}; struct problem_linear_constant {}; struct problem_nonlinear {}; struct ProblemBase { typedef DenseMatrix matrix_type; typedef DenseVector vector_type; const int m; const int n; const Real T; mutable DenseMatrix MA; mutable DenseMatrix MB; mutable DenseVector vg; ProblemBase(const int m, const int n, const double &T) : m(m), n(n), T(T), MA(m,n), MB(m,n), vg(m) { MA.clear(); MB.clear(); vg.clear(); } const DenseMatrix &A(const Real &) const { return MA; } const DenseMatrix &B(const Real &) const { return MB; } const DenseVector &g(const Real &) const { return vg; } const DenseMatrix &A(const Real &t, const DenseVector &u, const DenseVector &Du) const { return MA; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { return MB; } }; /* This is a problem due to */ struct ProblemDifficult : public ProblemBase { typedef problem_linear problem_type; const Real eta; ProblemDifficult(const Real &eta = -0.2) : ProblemBase(2,2, 3.0), eta(eta) {} const DenseMatrix &A(const Real &t) const { init(MA) = 0., 0., 1., eta*t; return MA; } const DenseMatrix &B(const Real &t) const { init(MB) = 1., eta*t, 0., eta+1.; return MB; } const DenseVector &g(const Real &t) const { init(vg) = exp(-t), 0.; return vg; } }; struct ProblemNonunique : public ProblemBase { typedef problem_linear problem_type; ProblemNonunique() : ProblemBase(2,2, 2.0) { init(MB) = 1., 0., 0., 1.; } const DenseMatrix &A(const Real &t) const { init(MA) = -t, t*t, -1., t; return MA; } }; // Example 2 from COLDAE paper of 1995. struct ProblemBVP : public ProblemBase { typedef problem_nonlinear problem_type; enum IndexType { X1 = 0, X2, X3, Y }; mutable DenseVector res; const Real epsilon; ProblemBVP(const Real &epsilon = 1.) : ProblemBase(4,4, 1.0), epsilon(epsilon) { res.resize(4); MA(0, X1) = 1.; MA(1, X2) = 1.; MA(2, X3) = 1.; } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { using utility::sqr; init(res) = Du[X1] - (epsilon + u[X2] - sin(t))*u[Y] - cos(t), Du[X2] - cos(t), Du[X3] - u[Y], (u[X1] - sin(t))*(u[Y] - exp(t)); return res; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { MB(0, X2) = -u[Y]; MB(0, Y) = -(epsilon + u[X2] - sin(t)); MB(2, Y) = -1.; MB(3, X1) = u[Y] - exp(t); MB(3, Y) = u[X1] - sin(t); return MB; } }; struct ProblemBVPSimplified : public ProblemBase { typedef problem_nonlinear problem_type; enum IndexType { X1 = 0, Y }; mutable DenseVector res; const Real epsilon; ProblemBVPSimplified(const Real &epsilon = 1.) : ProblemBase(2,2, 1.0), epsilon(epsilon) { res.resize(2); MA(0, X1) = 1.; } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { using utility::sqr; init(res) = Du[X1] - (epsilon + sin(t) - sin(t))*u[Y] - cos(t), (u[X1] - sin(t))*(u[Y] - exp(t)); return res; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { MB(0, Y) = -(epsilon + sin(t) - sin(t)); MB(1, X1) = u[Y] - exp(t); MB(1, Y) = u[X1] - sin(t); return MB; } }; struct ProblemSimple : public ProblemBase { typedef problem_nonlinear problem_type; enum IndexType { X1 = 0, }; mutable DenseVector res; ProblemSimple() : ProblemBase(1,1, 1.0) { res.resize(1); MA(0, X1) = 1.; } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { using utility::sqr; init(res) = Du[X1]; // Du[X1] - exp(t) - cos(t); return res; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { return MB; } }; // Periodically driven electronic amplifier from Chapter 7 of MK06. struct ProblemPDEA : public ProblemBase { typedef problem_nonlinear problem_type; mutable DenseVector res; ProblemPDEA() : ProblemBase(5,5, 0.01) { res.resize(5); const Real C1 = 1e-6; const Real C2 = 2e-6; const Real C3 = 3e-6; init(MA) = -C1, C1, 0., 0., 0., C1,-C1, 0., 0., 0., 0., 0.,-C2, 0., 0., 0., 0., 0.,-C3, C3, 0., 0., 0., C3,-C3; } const Real U_E(const Real &t) const { return 0.4 * sin(200.*M_PI*t); } const Real f(const Real &U) const { return 1e-6*(exp(U/0.026) - 1.); } const Real f_prime(const Real &U) const { return 1e-6/0.026*exp(U/0.026); } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { const Real U_B = 6.; const Real R0 = 1000.; const Real R1 = 9000.; const Real R2 = 9000.; const Real R3 = 9000.; const Real R4 = 9000.; const Real R5 = 9000.; const Real C1 = 1e-6; const Real C2 = 2e-6; const Real C3 = 3e-6; using utility::sqr; init(res) = (U_E(t) - u[0])/R0 + C1*(Du[1] - Du[0]), (U_B - u[1])/R2 - u[1]/R1 + C1*(Du[0] - Du[1]) - 0.01*f(u[1]-u[2]), f(u[1]-u[2]) - u[2]/R3 - C2*Du[2], (U_B - u[3])/R4 + C3*(Du[4]-Du[3]) - 0.99*f(u[1]-u[2]), -u[4]/R5 + C3*(Du[3]-Du[4]); return res; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { const Real R0 = 1000.; const Real R1 = 9000.; const Real R2 = 9000.; const Real R3 = 9000.; const Real R4 = 9000.; const Real R5 = 9000.; MB(0,0) = -1./R0; MB(1,1) = -1./R2 - 1./R1 - 0.01*f_prime(u[1]-u[2])*1.; MB(1,2) = -0.01*f_prime(u[1]-u[2])*(-1.); MB(2,1) = f_prime(u[1]-u[2])*1.; MB(2,2) = f_prime(u[1]-u[2])*(-1.) - 1./R3; MB(3,1) = -0.99*f_prime(u[1]-u[2])*1.; MB(3,2) = -0.99*f_prime(u[1]-u[2])*(-1.); MB(3,3) = -1./R4; MB(4,4) = -1./R5; return MB; } }; // Test Problem 13 from http://www.ma.ic.ac.uk/~jcash/BVP_software/readme.php#problems. struct ProblemLinearOrdinaryBVP : public ProblemBase { typedef problem_linear problem_type; const Real epsilon; ProblemLinearOrdinaryBVP(const Real &epsilon) : ProblemBase(2,2, 2.), epsilon(epsilon) { init(MA) = 0., epsilon, 1., 0.; init(MB) = -1., 0., 0.,-1.; } const DenseVector &g(const Real &t) const { init(vg) = -(epsilon*M_PI*M_PI + 1.)*cos(M_PI*(-1+t)), 0.; return vg; } }; struct ProblemNonlinearBVP : public ProblemBase { typedef problem_nonlinear problem_type; enum IndexType { X1 = 0, X2, Y, L1, L2, MU, NU, OM }; mutable DenseVector res; const Real ω ProblemNonlinearBVP(const Real &omega) : ProblemBase(6, 8, 2.), omega(omega) { res.resize(m); MA(0, MU) = 1.; MA(1, L1) = 1.; MA(2, L2) = 1.; MA(3, NU) = 1.; } Real fun_r(const Real &t) const { return sin(omega*t)/omega + cos(omega*t); } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { using utility::sqr; init(res) = Du[OM], Du[L1] + u[Y]*u[L1] - sqr(u[OM])*u[L2] + 2.*sqr(M_PI/3.)*u[X1]*u[MU] + (u[X1] + u[X2] - fun_r(t)), Du[L2] + u[L1] + u[Y]*u[L2] + 2.*u[X2]*u[MU] + (u[X1] + u[X2] - fun_r(t)), Du[NU] - 2.*u[OM]*u[X1]*u[L2], sqr(M_PI/3.)*sqr(u[X1]) + sqr(u[X2]) - 1., u[X1]*u[L1]+u[X2]*u[L2]; return res; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { using utility::sqr; MB(1, Y) = u[L1]; MB(1, L1) = u[Y]; MB(1, OM) = -2.*u[OM]*u[L2]; MB(1, L2) = -sqr(u[OM]); MB(1, X1) = 1. + 2.*sqr(M_PI/3.)*u[MU]; MB(1, MU) = 2.*sqr(M_PI/3.)*u[X1]; MB(1, X2) = 1.; MB(2, L1) = 1.; MB(2, Y) = u[L2]; MB(2, L2) = u[Y]; MB(2, X2) = 2.*u[MU] + 1.; MB(2, MU) = 2.*u[X2]; MB(2, X1) = 1.; MB(3, OM) = -2.*u[X1]*u[L2]; MB(3, X1) = -2.*u[OM]*u[L2]; MB(3, L2) = -2.*u[OM]*u[X1]; MB(4, X1) = 2.*sqr(M_PI/3.)*u[X1]; MB(4, X2) = 2.*u[X2]; MB(5, X1) = u[L1]; MB(5, L1) = u[X1]; MB(5, X2) = u[L2]; MB(5, L2) = u[X2]; return MB; } }; // The following two problems are presented in Mahavier, A Numerical Method Utilizing Weighted Sobolev Descent To Solve Singular Differential Equations, 1997. struct ProblemSingularity : public ProblemBase { typedef problem_linear problem_type; ProblemSingularity() : ProblemBase(1,1, 1.0) { init(MB) = -1.; } const DenseMatrix &A(const Real &t) const { init(MA) = 2.*t; return MA; } }; struct ProblemSingularity2 : public ProblemBase { typedef problem_nonlinear problem_type; mutable DenseVector res; ProblemSingularity2() : ProblemBase(1,1, 1.) { assert(n == m); res.resize(n); } const DenseVector &F(const Real &t, const DenseVector &u, const DenseVector &Du) const { res(0) = t*t*Du(0) - 2.*t*u(0) - u(0)*u(0); return res; } const DenseMatrix &A(const Real &t, const DenseVector &u, const DenseVector &Du) const { MA(0,0) = t*t; return MA; } const DenseMatrix &B(const Real &t, const DenseVector &u, const DenseVector &Du) const { MB(0,0) = -2.*t - 2.*u(0); return MB; } }; struct ProblemStiffness : public ProblemBase { typedef problem_linear problem_type; ProblemStiffness() : ProblemBase(1,1, 1.0) { const Real K = -15.; init(MA) = 1.; init(MB) = -1. * K; } }; struct ProblemConstantSmall : public ProblemBase { typedef problem_linear problem_type; ProblemConstantSmall() : ProblemBase(2,2, 1.0) { init(MA) = 1., 1., 0., 0.; init(MB) = 0., 0., 0., 1.; } const DenseVector &g(const Real &t) const { init(vg) = exp(t)+cos(t), exp(t); return vg; } }; struct ProblemConstantTest : public ProblemBase { typedef problem_linear problem_type; ProblemConstantTest() : ProblemBase(2,2, 1.0) { init(MA) = 1., 0., 0., 0.; init(MB) = 0., 1., 0., 1.; } const DenseVector &g(const Real &t) const { init(vg) = 0, t; return vg; } }; struct ProblemConstant : public ProblemBase { typedef problem_linear problem_type; ProblemConstant(int m) : ProblemBase(m,m, 1.) { MA.clear(); for (int i=0; i0) MA(i,i) = 1; if (i0) MB(i,i-1) = 1; } } const DenseVector &operator ()(const Real &t) const { vg(0) = -3.*t*t + 6.*t; for (int i=1; i 0.); // if (y(1) <= 0.) throw InvalidInput("Problem chemakzo: y(1)<0 and we need square root."); double r1 = k1*pow(y(0),4)*sqrt(fabs(y(1))); double r2 = k2*y(2)*y(3); double r3 = k2/kbig*y(0)*y(4); double r4 = k3*y(0)*pow(y(3),2); double r5 = k4*pow(y(5),2)*sqrt(fabs(y(1))); double fin = kla*(po2/hen-fabs(y(1))); f(0) = -2*r1 +r2 -r3 -r4; f(1) = -0.5*r1 -r4 -0.5*r5 + fin; f(2) = r1 -r2 +r3; f(3) = -r2 +r3 -2*r4; f(4) = r2 -r3 +r5; f(5) = ks*y(0)*y(3)-y(5); ublas::noalias(f) += ublas::prod(MA, yprime); return f; } const DenseMatrix &B(const Real &t, const DenseVector &y, const DenseVector &yprime) const { using utility::sign; DenseMatrix &dfdy = MB; const double k1 = 18.7; const double k2 = 0.58; const double k3 = 0.09; const double k4 = 0.42; const double kbig = 34.4; const double kla = 3.3; const double ks = 115.83; // assert(y(1) > 0.); // if (y(1) <= 0.) throw InvalidInput("Problem chemakzo: y(1)<0 and we need square root."); const double r11 = 4*k1*pow(y(0),3)*sqrt(fabs(y(1)))*sign(y(1)); const double r12 = 0.5*k1*pow(y(0),4)/sqrt(fabs(y(1)))*sign(y(1)); const double r23 = k2*y(3); const double r24 = k2*y(2); const double r31 = (k2/kbig)*y(4); const double r35 = (k2/kbig)*y(0); const double r41 = k3*pow(y(3),2); const double r44 = 2*k3*y(0)*y(3); const double r52 = 0.5*k4*pow(y(5),2)/sqrt(fabs(y(1)))*sign(y(1)); const double r56 = 2*k4*y(5)*sqrt(fabs(y(1)))*sign(y(1)); const double fin2 = -kla; dfdy(0,0) = -2*r11-r31-r41; dfdy(0,1) = -2*r12; dfdy(0,2) = r23; dfdy(0,3) = r24-r44; dfdy(0,4) = -r35; dfdy(1,0) = -0.5*r11-r41; dfdy(1,1) = -0.5*r12-0.5*r52+fin2; dfdy(1,3) = -r44; dfdy(1,5) = -0.5*r56; dfdy(2,0) = r11+r31; dfdy(2,1) = r12; dfdy(2,2) = -r23; dfdy(2,3) = -r24; dfdy(2,4) = r35; dfdy(3,0) = r31-2*r41; dfdy(3,2) = -r23; dfdy(3,3) = -r24-2*r44; dfdy(3,4) = r35; dfdy(4,0) = -r31; dfdy(4,1) = r52; dfdy(4,2) = r23; dfdy(4,3) = r24; dfdy(4,4) = -r35; dfdy(4,5) = r56; dfdy(5,0) = ks*y(3); dfdy(5,3) = ks*y(0); dfdy(5,5) = -1; return MB; } const DenseVector &initial() const { DenseVector &y = init_y; const double ks = 115.83; y(0) = 0.444; y(1) = 0.00123; y(2) = 0; y(3) = 0.007; y(4) = 0; y(5) = ks*y(0)*y(3); return init_y; } const DenseVector &initial_deriv() const { init_yprime = F(0, initial(), ScalarVector(n, 0.)); return init_yprime; } const DenseVector &solution() const { DenseVector &y = sol; y(0) = 0.1150794920661702e0; y(1) = 0.1203831471567715e-2; y(2) = 0.1611562887407974e0; y(3) = 0.3656156421249283e-3; y(4) = 0.1708010885264404e-1; y(5) = 0.4873531310307455e-2; return sol; } }; // Problem 13 of the initial value problemset: Andrew's squeezing mechanism struct ProblemAndrewsConstants { const Real m1; const Real m2; const Real m3; const Real m4; const Real m5; const Real m6; const Real m7; const Real xa; const Real ya; const Real xb; const Real yb; const Real xc; const Real yc; const Real c0; const Real i1; const Real i2; const Real i3; const Real i4; const Real i5; const Real i6; const Real i7; const Real d; const Real da; const Real e; const Real ea; const Real rr; const Real ra; const Real l0; const Real ss; const Real sa; const Real sb; const Real sc; const Real sd; const Real ta; const Real tb; const Real u; const Real ua; const Real ub; const Real zf; const Real zt; const Real fa; const Real mom; ProblemAndrewsConstants() : m1(.04325e0), m2(.00365e0), m3(.02373e0), m4(.00706e0), m5(.07050e0), m6(.00706e0), m7(.05498e0), xa(-.06934e0), ya(-.00227e0), xb(-0.03635e0), yb(.03273e0), xc(.014e0), yc(.072e0), c0(4530e0), i1(2.194e-6), i2(4.410e-7), i3(5.255e-6), i4(5.667e-7), i5(1.169e-5), i6(5.667e-7), i7(1.912e-5), d(28e-3), da(115e-4), e(2e-2), ea(1421e-5), rr(7e-3), ra(92e-5), l0(7785e-5), ss(35e-3), sa(1874e-5), sb(1043e-5), sc(18e-3), sd(2e-2), ta(2308e-5), tb(916e-5), u(4e-2), ua(1228e-5), ub(449e-5), zf(2e-2), zt(4e-2), fa(1421e-5), mom(33e-3) {} }; struct ProblemAndrewsIndex3 : public ProblemBase, public ProblemAndrewsConstants { typedef problem_nonlinear problem_type; mutable DenseVector ff; mutable DenseVector init_y; mutable DenseVector final_y; mutable DenseVector init_yprime; ProblemAndrewsIndex3(const Real &T = 3e-2) : ProblemBase(27,27, T) { ff.resize(m); init_y.resize(n); final_y.resize(n); init_yprime.resize(n); for (int i=0; i<14; i++) MA(i,i) = -1.0; } const DenseVector &F(const Real &t, const DenseVector &y, const DenseVector &yprime) const { using utility::sqr; const Real sibe = sin(y(0)); const Real sith = sin(y(1)); const Real siga = sin(y(2)); const Real siph = sin(y(3)); const Real side = sin(y(4)); const Real siom = sin(y(5)); const Real siep = sin(y(6)); const Real cobe = cos(y(0)); const Real coth = cos(y(1)); const Real coga = cos(y(2)); const Real coph = cos(y(3)); const Real code = cos(y(4)); const Real coom = cos(y(5)); const Real coep = cos(y(6)); const Real sibeth = sin(y(0)+y(1)); const Real siphde = sin(y(3)+y(4)); const Real siomep = sin(y(5)+y(6)); const Real cobeth = cos(y(0)+y(1)); const Real cophde = cos(y(3)+y(4)); const Real coomep = cos(y(5)+y(6)); const Real bep = y(7); const Real thp = y(8); const Real php = y(10); const Real dep = y(11); const Real omp = y(12); const Real epp = y(13); DenseMatrix m(7,7); m.clear(); m(0,0) = m1*sqr(ra) + m2*(sqr(rr)-2*da*rr*coth+sqr(da)) + i1 + i2; m(1,0) = m2*(sqr(da)-da*rr*coth) + i2; m(1,1) = m2*sqr(da) + i2; m(2,2) = m3*(sqr(sa)+sqr(sb)) + i3; m(3,3) = m4*sqr(e-ea) + i4; m(4,3) = m4*(sqr(e-ea)+zt*(e-ea)*siph) + i4; m(4,4) = m4*(sqr(zt)+2*zt*(e-ea)*siph+sqr(e-ea)) + m5*(sqr(ta)+sqr(tb)) + i4 + i5; m(5,5) = m6*sqr(zf-fa) + i6; m(6,5) = m6*(sqr(zf-fa)-u*(zf-fa)*siom) + i6; m(6,6) = m6*(sqr(zf-fa)-2*u*(zf-fa)*siom+sqr(u)) + m7*(sqr(ua)+sqr(ub)) + i6 + i7; for (int j=1; j<7; j++) for (int i=0; i Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: main.cc 413 2008-02-11 14:41:09Z msauter $ */ // STL headers. #include #include #include #include #include #include #include #include #include #include #include "logging.h" #include "utility.hxx" #include "type.hxx" #include "solvers.hxx" #include "problems.hxx" #include "descent.hxx" void testcase_numerically_difficult() { using namespace std; using namespace problems; using namespace steepest_descent; const int N = 1000; const Real lambda = 1.e-3; const Real damping = 0.85; const SobolevNorm style = NORM_GRAPH; const int MAX_STEPS = 10000; const Real eta = -0.8; typedef vector tVI; tVI steps; for (int i=0; i<100; i++) steps.push_back(1); for (int i=0; i<40; i++) steps.push_back(10); for (int i=0; i<30; i++) steps.push_back(50); for (int i=0; i<8; i++) steps.push_back(1000); ProblemDifficult problem(eta); EmptySupplementaryConditions supp(problem, N); SteepestDescent > sd(supp); int plot_cnt = 0; for (int k=0; k<=sd.N; k++) { DenseVector tmp(sd.problem.n); init(tmp) = 2., 2.; sd.set_current_estimate(k, tmp); } ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); gnuplot_output(sd, data); data << endl << endl; ++plot_cnt; { Real avg_error = 0.; Real max_error = 0.; for (int k=0; k<=sd.N; k++) { DenseVector tmp(sd.problem.n); sd.get_current_estimate(k, tmp); const Real t = k*sd.delta; DenseVector sol(sd.problem.n); init(sol) = (1.-eta*t)*exp(-t), exp(-t); tmp -= sol; max_error = max(max_error, ublas::norm_inf(tmp)); avg_error += ublas::inner_prod(tmp, tmp); } avg_error *= sd.problem.T / (sd.N+1.); sd.init_descent(style, sd.u); LOG(INFO) << "START " << sd.eval_psi(sd.u) << " " << avg_error << " " << max_error << endl; } for (tVI::size_type j=0; j= MAX_STEPS || break_) break; } LOG(INFO) << "Number of generated plots: " << plot_cnt << endl; } void testcase_singularity() { using namespace std; using namespace problems; using namespace steepest_descent; using utility::sqr; // stringstream ssdata; // ssdata.setf(ios::scientific); // ssdata << "singular_data_" << size[isize] << SOBOLEV_NORM_NAME[style[istyle]] << lambda[ilambda] << ".dat"; const int N = 10000; const Real lambda = 1.; const Real damping = 0.85; const SobolevNorm style = NORM_WEIGHTED; const int MAX_STEPS = 1000; LOG(INFO) << "grid size: " << N << endl; LOG(INFO) << "lambda: " << lambda << endl; LOG(INFO) << "damping: " << damping << endl; LOG(INFO) << "gradient: " << SOBOLEV_NORM_NAME[style] << endl; typedef vector tVI; tVI steps; for (int i=0; i<100; i++) steps.push_back(1); for (int i=0; i<40; i++) steps.push_back(10); for (int i=0; i<30; i++) steps.push_back(50); for (int i=0; i<8; i++) steps.push_back(1000); ProblemSingularity2 problem; DirichletSupplementaryConditions supp(problem, N); supp.fix_value(0, N); SteepestDescent > sd(supp); for (int k=0; k<=sd.N; k++) { const Real t = k*sd.delta; DenseVector tmp(sd.problem.n); tmp(0) = t; // tmp(0) = t*t/(2.-t); // exact solution sd.set_current_estimate(k, tmp); } { Real avg_error = 0.; Real max_error = 0.; for (int k=0; k<=sd.N; k++) { DenseVector tmp(sd.problem.n); sd.get_current_estimate(k, tmp); const Real t = k*sd.delta; tmp(0) -= t*t/(2.-t); max_error = max(max_error, fabs(tmp(0))); avg_error += sqr(tmp(0)); } avg_error *= sd.problem.T / (sd.N+1.); LOG(INFO) << "START " << sd.eval_psi(sd.u) << " " << avg_error << " " << max_error << endl; } for (tVI::size_type j=0; j= MAX_STEPS || break_) break; } } void testcase_figure_eight() { using namespace std; using namespace problems; using namespace steepest_descent; using utility::rand_uniform; ProblemFigureEight problem; EmptySupplementaryConditions supp(problem, 300); SteepestDescent > sd(supp); ofstream data("figure_eight_dim.dat"); data.precision(16); data.setf(ios::fixed); for (int i=0; i<10000; i++) { DenseVector tmp1(2), tmp2(2); init(tmp1) = rand_uniform(-2.,2.), rand_uniform(-2.,2.); init(tmp2) = rand_uniform(-2.,2.), rand_uniform(-2.,2.); for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/sd.problem.T; sd.set_current_estimate(k, (1.-lambda)*tmp1 + lambda*tmp2); } sd.descent(NORM_GRAPH, 30, 0.85, 1.e-5); DenseVector init(2); sd.get_current_estimate(0, init); data << init(0) << " " << init(1) << endl; } } void testcase_dim() { using namespace std; using namespace problems; using namespace steepest_descent; using utility::rand_uniform; /* ProblemLinearDim problem(ProblemLinearDim::INDEX0); EmptySupplementaryConditions supp(problem, 1000); SteepestDescent > sd(supp); */ ProblemLinearDimBig problem; EmptySupplementaryConditions supp(problem, 100); SteepestDescent > sd(supp); ofstream full("data.dat"); full.precision(25); full.setf(ios::fixed); ofstream data("linear_dim.dat"); data.precision(25); data.setf(ios::fixed); for (int i=0; i<500; i++) { DenseVector tmp1(problem.n), tmp2(problem.n); for (int j=0; j supp(problem, 500); supp.fix_value(0,0); supp.fix_value(1,0); SteepestDescent > sd(supp); ofstream data("nonunique_dim.dat"); data.precision(16); data.setf(ios::fixed); for (int i=0; i<100; i++) { DenseVector tmp1(2), tmp2(2); init(tmp1) = 0., 0.; init(tmp2) = rand_uniform(-2.,2.), rand_uniform(-2.,2.); for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/sd.problem.T; sd.set_current_estimate(k, (1.-lambda)*tmp1 + lambda*tmp2); } sd.descent(NORM_GRAPH, 1000, 0.85, 1.e-2); gnuplot_output(sd, data); // gnuplot: to seperate multiple plots in a single file data << endl << endl; } } void testcase_bvp() { using namespace std; using namespace problems; using namespace steepest_descent; using utility::rand_uniform; /* ProblemBVP problem(1.); DirichletSupplementaryConditions supp(problem, 1000); supp.fix_value(0, 0); supp.fix_value(1, supp.N); supp.fix_value(2, 0); SteepestDescent > sd(supp); ofstream data("bvp_nonunique.dat"); data.precision(25); data.setf(ios::fixed); for (int i=0; i<100; i++) { DenseVector tmp1(4), tmp2(4); init(tmp1) = sin(0.), rand_uniform(-2.,2.), 1., rand_uniform(-20.,20.); init(tmp2) = rand_uniform(-2.,2.), sin(1.), rand_uniform(-2.,2.), rand_uniform(-20.,20.); // init(tmp1) = sin(0.), 2.000, 1., 0.000; // init(tmp2) = 3.000, sin(1.), 1.000, 0.000; for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/sd.problem.T; sd.set_current_estimate(k, (1.-lambda)*tmp1 + lambda*tmp2); // init(tmp1) = sin(h), sin(h), 1., 0.; // init(tmp1) = sin(h)+exp(h)-1., sin(h), exp(h), exp(h); // sd.set_current_estimate(k, tmp1); } try { sd.descent(NORM_GRAPH, 200, 0.85, 1e-6); } catch (std::exception &e) { LOG(INFO) << e.what() << endl; } // gnuplot: to seperate multiple plots in a single file accessible by the keyword index gnuplot_output(sd, data); data << endl << endl; } */ ProblemBVPSimplified problem(1.); DirichletSupplementaryConditions supp(problem, 100); supp.fix_value(0, 0); SteepestDescent > sd(supp); ofstream data("bvp_nonunique_simple.dat"); data.precision(25); data.setf(ios::fixed); for (int i=0; i<100; i++) { LOG(INFO) << "TRY NUMBER " << i+1 << endl; DenseVector tmp1(2), tmp2(2); init(tmp1) = sin(0.), rand_uniform(-10.,10.); init(tmp2) = rand_uniform(-2.,2.), rand_uniform(-10.,10.); // init(tmp1) = 0.00000000000000000000000000000000000, 6.23279519028290707183259655721485615; // init(tmp2) = 0.29218420972319725237298371212091297, -3.07779168065431729672809524345211685; LOG(INFO) << "tmp1: " << tmp1 << endl; LOG(INFO) << "tmp2: " << tmp2 << endl; for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/sd.problem.T; sd.set_current_estimate(k, (1.-lambda)*tmp1 + lambda*tmp2); } try { sd.descent(NORM_GRAPH, 80, 0.85, 1e-6); // sd.descent(NORM_H1, 10000, 0.85, 1.); } catch (std::exception &e) { LOG(INFO) << e.what() << endl; } gnuplot_output(sd, data); data << endl << endl; } #if 0 ProblemSimple problem; DirichletSupplementaryConditions supp(problem, 1000); supp.fix_value(0, 10); supp.fix_value(0, 501); supp.fix_value(0, 990); SteepestDescent > sd(supp); ofstream data("data.dat"); data.precision(25); data.setf(ios::fixed); // for (int i=0; i<100; i++) { /* for (int k=0; k<=10; k++) { DenseVector tmp1(1); tmp1(0) = 0; sd.set_current_estimate(k, tmp1); sd.set_current_estimate(1000-k, tmp1); } for (int k=11; k<=501; k++) { DenseVector tmp1(1); tmp1(0) = (k-10.)/491.; sd.set_current_estimate(k, tmp1); } for (int k=502; k<990; k++) { DenseVector tmp1(1); tmp1(0) = 1.-(k-501.)/489.; sd.set_current_estimate(k, tmp1); } */ for (int k=0; k<=100; k++) { DenseVector tmp1(1); tmp1(0) = 0.; sd.set_current_estimate(k, tmp1); sd.set_current_estimate(1000-k, tmp1); } for (int k=101; k<900; k++) { DenseVector tmp1(1); tmp1(0) = 1.; sd.set_current_estimate(k, tmp1); } try { // sd.descent(NORM_GRAPH, 80, 0.85, 1e-6); sd.descent(NORM_H1, 250, 0.85, 1.); } catch (std::exception &e) { LOG(INFO) << e.what() << endl; } gnuplot_output(sd, data); data << endl << endl; } #endif } void testcase_ascher_petzold() { using namespace std; using namespace problems; using namespace steepest_descent; /* { ProblemAscherPetzold problem; DirichletSupplementaryConditions supp(problem, 300); for (int i=0; i<3; i++) supp.fix_value(i, 0); SteepestDescent > sd(supp); for (int k=0; k<=sd.N; k++) sd.set_current_estimate(k, problem.initial()); sd.descent(NORM_GRAPH, 30, 0.85, 1.e-5); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); gnuplot_output(sd, data); } */ using utility::rand_uniform; ProblemAscherPetzold problem; EmptySupplementaryConditions supp(problem, 300); SteepestDescent > sd(supp); ofstream data("ascher_petzold.dim.dat"); data.precision(16); data.setf(ios::fixed); for (int i=0; i<10; i++) { DenseVector tmp1(3), tmp2(3); init(tmp1) = rand_uniform(-2.,2.), rand_uniform(-2.,2.), rand_uniform(-2.,2.); init(tmp2) = rand_uniform(-2.,2.), rand_uniform(-2.,2.), rand_uniform(-2.,2.); for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/sd.problem.T; sd.set_current_estimate(k, (1.-lambda)*tmp1 + lambda*tmp2); } sd.descent(NORM_GRAPH, 30, 0.85, 1.e-5); DenseVector init(3); sd.get_current_estimate(0, init); data << init(0) << " " << init(1) << " " << init(2) << endl; } } void testcase_andrews() { using namespace std; using namespace problems; using namespace steepest_descent; /* const int STEPS = 100; const Real Tstep = 3e-2/STEPS; ProblemAndrewsIndex1Small problem(Tstep); DirichletSupplementaryConditions supp(problem, 5000); for (int i=0; i<20; i++) supp.fix_value(i, 0); SteepestDescent > sd(supp); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); DenseVector next = problem.initial(); for (int step=0; step tVDV; tVDV prev; prev.push_back(problem.initial()); for (int step=0; step supp(problem, 50*(step+1)); for (int i=0; i<20; i++) supp.fix_value(i, 0); SteepestDescent > sd(supp); for (int k=0; k supp(problem, 100); for (int i=0; i<7; i++) supp.fix_value(i, 0); SteepestDescent > sd(supp); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); typedef vector tVDV; tVDV prev; prev.push_back(problem.initial()); for (int step=0; step 2) { // refine LOG(INFO) << "Refinement Step " << step+1 << endl; ProblemAndrewsIndex1Small problem2(Tstep*4); DirichletSupplementaryConditions supp2(problem, 100*4); for (int i=0; i<7; i++) supp2.fix_value(i, 0); SteepestDescent > sd2(supp2); for (int k=0; k<=sd2.N; k++) sd2.set_current_estimate(k, prev[prev.size()-400+k-1]); sd2.descent(NORM_H1, 5, 0.85, 1); sd2.descent(NORM_GRAPH, 20, 0.85, 1e-5); DenseVector tmp; sd2.get_current_estimate(sd2.N, tmp); prev.pop_back(); prev.push_back(tmp); } } */ ProblemAndrewsIndex3 problem; DirichletSupplementaryConditions supp(problem, 10000); for (int i=0; i<27; i++) supp.fix_value(i, 0); SteepestDescent > sd(supp); ifstream input("../input/sol.andrews.10000.dat"); gnuplot_input(sd, input); using utility::rand_uniform; DenseVector tmp1(problem.n), tmp2(problem.n); for (int i=0; i<27; i++) { tmp1(i) = 0.; tmp2(i) = 0.02*rand_uniform(-2.,2.); } for (int k=0; k<=sd.N; k++) { const Real h = k*sd.delta; const Real lambda = h/problem.T; DenseVector tmp(problem.n); sd.get_current_estimate(k, tmp); sd.set_current_estimate(k, tmp + (1.-lambda)*tmp1 + lambda*tmp2); } /* for (int k=0; k<=sd.N; k++) { const Real h = k * sd.delta; sd.set_current_estimate(k, problem.initial()); } */ sd.descent(NORM_H1, 10, 0.85, 1); sd.descent(NORM_GRAPH, 20, 0.85, 1e-8); ofstream data("data.dat"); data.precision(25); data.setf(ios::fixed); gnuplot_output(sd, data); } void testcase_lorenz_attractor() { using namespace std; using namespace problems; using namespace steepest_descent; ProblemLorenz problem(800.); EmptySupplementaryConditions supp(problem, 160000); // for (int i=0; i<3; i++) // supp.fix_value(i, 0); SteepestDescent > sd(supp); ifstream input("data.dat"); gnuplot_input(sd, input); // ifstream input("input/lorenz.dat"); // ifstream input("backup/lorenz3/data.dat"); // ifstream input("input/butterfly.dat"); // gnuplot_input(sd, input); /* for (int k=0; k<=sd.N; k++) { assert(sd.problem.n == 3); DenseVector tmp(3); // init(tmp) = sqrt(72.), sqrt(72.), 27.; init(tmp) = 10.,12.,14.; // init(tmp) = 3.,15.,1.; // init(tmp) = 2.5450919789293978, 5.7573376958333045, -2.6939528375278199; // init(tmp) = 10.0094834215091, 7.87724239501250, 26.3369924246729; sd.set_current_estimate(k, tmp); } */ // sd.descent(NORM_H1, 40, 0.85, 1.); sd.descent(NORM_GRAPH, 40, 0.85, 1.e-4); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); gnuplot_output(sd, data); } void testcase_scaling() { using namespace std; using namespace problems; using namespace steepest_descent; using utility::rand_uniform; ofstream out("data.dat"); ProblemScaling problem; DirichletSupplementaryConditions supp(problem, 1000); supp.fix_value(1,0); SteepestDescent > sd(supp); for (int k=0; k<=sd.N; k++) { // const Real t = k*sd.delta; DenseVector tmp(sd.problem.n); init(tmp) = 1., 1.; // init(tmp) = sin(t), exp(7.*sin(t)); sd.set_current_estimate(k, tmp); } try { sd.descent(NORM_GRAPH, 100, 0.85, 1.e-5); } catch (std::exception &e) { LOG(INFO) << e.what() << endl; } gnuplot_output(sd, out); out << endl << endl; } void testcase_sonic() { using namespace std; using namespace problems; using namespace steepest_descent; ProblemSonic problem; DirichletSupplementaryConditions supp(problem, 1000); supp.fix_value(ProblemSonic::RHO, 0); supp.fix_value(ProblemSonic::RHO, 515); SteepestDescent > sd(supp); for (int k=0; k<=sd.N; k++) { DenseVector tmp(3); tmp(ProblemSonic::PHI) = 1.; tmp(ProblemSonic::E) = 1.; tmp(ProblemSonic::RHO) = problem.rho_bar; sd.set_current_estimate(k, tmp); } sd.descent(NORM_GRAPH, 100, 0.85, 1.); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); gnuplot_output(sd, data); } void testcase_chemakzo() { using namespace std; using namespace problems; using namespace steepest_descent; /* ProblemChemakzo problem; DirichletSupplementaryConditions supp(problem, 10000); for (int i=0; i > sd(supp); for (int i=0; i<=sd.N; i++) sd.set_current_estimate(i, problem.initial()); sd.descent(NORM_GRAPH, 80, 0.85, 1e-5); ofstream data("data.dat"); data.precision(16); data.setf(ios::fixed); gnuplot_output(sd, data); */ // T = 0.05 ProblemChemakzo problem(0.05); SupplementaryConditions supp(problem, 100); for (int i=0; i > sd(supp); DenseVector next = problem.initial(); for (int j=0; j<180*2*10; j++) { cout << j*0.05 << ": " << next << endl; for (int i=0; i<=sd.N; i++) sd.set_current_estimate(i, next); sd.descent(NORM_GRAPH, 100, 1.0); sd.get_current_estimate(sd.N, next); } gnuplot_output(sd, cout); } int main() { using namespace std; using namespace logging; utility::srand(time(NULL)); cout.precision(35); cout.setf(ios::fixed); // Initialization of the logging. ofstream logfile("output.log"); tee_streambuf logbuf(cout.rdbuf(), logfile.rdbuf()); tee_streambuf errbuf(cerr.rdbuf(), logfile.rdbuf()); ostream logstream(&logbuf); ostream errstream(&errbuf); logfile.precision(35); logfile.setf(ios::fixed); logstream.precision(35); logstream.setf(ios::fixed); errstream.precision(35); errstream.setf(ios::fixed); { tLogger &log = tLogger::getLogger(); log.tie(MASK_ALL, &errstream); log.tie(DEBUG, NULL /*&logfile*/); log.tie(INFO, &logstream); } boost::timer timer; try { // testcase_figure_eight(); // DONE // testcase_nonunique(); // DONE // testcase_singularity(); // DONE // testcase_numerically_difficult(); // DONE testcase_bvp(); // DONE // testcase_dim(); // DONE // testcase_scaling(); // DONE // testcase_andrews(); // testcase_chemakzo(); // testcase_sonic(); // testcase_lorenz_attractor(); // testcase_ascher_petzold(); } catch (const char *e) { LOG(ERROR) << e << endl; } LOG(INFO) << "Overall timing: " << timer.elapsed() << " sec" << endl; return 0; } sgdae/logging.h0000644000175000017500000001172110754367671013704 0ustar msautermsauter/* This file is part of SGDAE, a software to numerically solve differential algebraic equations using a steepest descent method based on Sobolev gradients. You are welcome to contact the authors via e-mail: Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __LOGGING_HEADER__ #define __LOGGING_HEADER__ #include #include #include #include #include // TODO: What about supporting boost::iostreams? // http://www.boost.org/libs/iostreams/doc/index.html namespace logging { using std::endl; typedef std::vector tVOS; typedef std::vector tVS; template > class basic_null_streambuf : public std::basic_streambuf { typedef typename Traits::int_type int_type; protected: int_type overflow(int_type c) { return Traits::not_eof(c); } std::streamsize xsputn(const CT *s, std::streamsize n) { return n; } public: basic_null_streambuf() {} }; template > class basic_null_ostream: public std::basic_ostream { public: basic_null_ostream() : std::basic_ios(&m_sbuf), std::basic_ostream(&m_sbuf) { init(&m_sbuf); } private: basic_null_streambuf m_sbuf; }; typedef basic_null_ostream tNull_ostream; // Slight adaption from the code of "Tee streams in C++" on // http://www.cs.technion.ac.il/~imaman/programs/programs.html template > class basic_tee_stream : std::basic_ostream { typedef std::basic_ostream SuperType; public: basic_tee_stream(std::ostream &o1, std::ostream &o2) : SuperType(o1.rdbuf()), o1_(o1), o2_(o2) { } basic_tee_stream &operator <<(SuperType &(*manip)(SuperType &)) { o1_ << manip; o2_ << manip; return *this; } template basic_tee_stream &operator <<(const T& t) { o1_ << t; o2_ << t; return *this; } private: std::ostream &o1_; std::ostream &o2_; }; // Adapted version from http://www.ddj.com/cpp/184403387 template > class basic_tee_streambuf : public std::basic_streambuf { typedef typename std::basic_streambuf sb_type; typedef typename Traits::int_type int_type; public: basic_tee_streambuf(sb_type *s1, sb_type *s2) : buf1(s1), buf2(s2) {} ~basic_tee_streambuf() { sync(); } protected: std::streamsize xsputn(const CT *s, std::streamsize n) { std::streamsize res1 = buf1->sputn(s, n); std::streamsize res2 = buf2->sputn(s, n); return std::min(res1, res2); } int_type overflow(int_type c) { buf1->sputc(c); buf2->sputc(c); return c; } int sync() { if (-1 == buf1->pubsync()) return -1; return buf2->pubsync(); } private: sb_type *buf1; sb_type *buf2; }; typedef basic_tee_streambuf tee_streambuf; enum tLogType { DEBUG = 0, INFO, WARNING, ERROR, FATAL, LOG_TYPE_END, MASK_ALL, LOG_MASK_END }; class tLogger : public std::ostream { private: std::string name[LOG_TYPE_END]; std::ostream *os[LOG_TYPE_END]; tVS scope_stack; static tNull_ostream null_os; static tLogger *logger; tLogger(); void pushScope(const std::string &scope); void popScope(); public: static tLogger &getLogger() { if (logger == NULL) logger = new tLogger; return *logger; } void tie(const tLogType type, std::ostream *out); std::ostream *get_tie(const tLogType type); void setName(const tLogType, const std::string &); bool isLogTypeLogged(const tLogType type) const { assert(type < LOG_TYPE_END); return os[type] != NULL; } std::ostream &operator ()(const tLogType type = INFO); friend class tLogScope; }; class tLogScope { public: tLogScope(const std::string &env) { this->getLogger()(DEBUG) << "entering " << env << endl; tLogger::getLogger().pushScope(env); } virtual ~tLogScope() { tLogger::getLogger().popScope(); this->getLogger()(DEBUG) << "left scope" << endl; } bool isLogTypeLogged(const tLogType type) const { return tLogger::getLogger().isLogTypeLogged(type); } tLogger &getLogger() const { return tLogger::getLogger(); } std::ostream &operator ()(const tLogType type) const { return this->getLogger()(type); } }; #define LOG(type) (tLogger::getLogger().isLogTypeLogged(type)) && tLogger::getLogger()(type) #define SCOPE(name) tLogScope scope(name); }; #endif sgdae/descent.hxx0000644000175000017500000010154010754367672014263 0ustar msautermsauter/* This file is part of SGDAE, a software to numerically solve differential algebraic equations using a steepest descent method based on Sobolev gradients. You are welcome to contact the authors via e-mail: Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __DESCENT_HXX__ #define __DESCENT_HXX__ namespace steepest_descent { enum SobolevNorm { NORM_H1, NORM_EUCLID, NORM_EUCLIDEAN = NORM_EUCLID, NORM_GRAPH, NORM_H1GRAPH, NORM_WEIGHTED, NORM_WEIGHTED1 = NORM_WEIGHTED, NORM_WEIGHTED2, LEAST_SQUARES }; const std::string SOBOLEV_NORM_NAME[] = { "H1", "EU", "GR", "G1", "W1", "W2", "LS" }; using ublas::prod; using ublas::trans; using ublas::norm_2; using ublas::noalias; using ublas::subrange; using ublas::slice; using ublas::range; using std::string; using std::setw; using namespace logging; template struct DiscretizationBase { typedef typename P::problem_type problem_type; const int N; const Real delta; const P &problem; DenseVector u; SparseMatrix D0, D0tD0; SparseMatrix D1, D1tD1; SparseMatrix H1; SparseMatrix S; solver::MatrixType type_S; SparseMatrix W1, W2; SparseMatrix Q; SparseMatrix QtQ; DenseVector g; DiscretizationBase(const int N, const P &problem) : N(N), delta(problem.T/N), problem(problem) { SCOPE("constructor DiscretizationBase"); LOG(DEBUG) << "Global initialization" << endl; type_S = solver::UNINITIALIZED; init_D(); init_g(); } virtual ~DiscretizationBase() {} private: virtual void init_D() { SCOPE("init_D"); LOG(DEBUG) << "Initialize matrices D0, D1, D0tD0" << endl; D0 = IdentityMatrix(N+1); D0tD0 = IdentityMatrix(N+1); D1.resize(N+1, N+1, false); D1.clear(); D1(0,0) = -3.; D1(0,1) = 4.; D1(0,2) = -1.; for (int k=1; kN || j<0) continue; for (int k=i-2; k<=i+2; k++) { if (k>N || k<0) continue; if (abs(i-k)>2 || abs(j-k)>2) continue; D1tD1(i,j) += D1(k,i)*D1(k,j); } } LOG(DEBUG) << "Initialize matrix H1" << endl; H1.resize((N+1)*problem.n,(N+1)*problem.n, false); H1.clear(); for (int j=0; j<=N; j++) for (int i=0; iN || k<0) continue; H1(j*problem.n+i, k*problem.n+i) = D1tD1(j,k); } // H1(j*problem.n+i, j*problem.n+i) += 1.; // Then H1 alone would be the matrix connected with the H1 inner product. } } virtual void init_Q() { SCOPE("init_Q"); LOG(DEBUG) << "Initialize matrix Q" << endl; Q.resize(problem.m*(N+1), problem.n*(N+1), false); for (int i=0; i<=N; i++) for (int j=i-2; j<=i+2; j++) { if (j>N || j<0) continue; noalias(project(Q, range(i*problem.m,(i+1)*problem.m), range(j*problem.n,(j+1)*problem.n))) += D1(i,j)*cache_A[i] + D0(i,j)*cache_B[i]; } LOG(DEBUG) << "Initialize matrix W1" << endl; W1.resize(problem.n*(N+1), problem.n*(N+1), false); for (int i=0; i<=N; i++) for (int j=i-2; j<=i+2; j++) { if (j>N || j<0) continue; for (int k=i-2; k<=i+2; k++) { if (k>N || k<0) continue; if (abs(i-k)>2 || abs(j-k)>2) continue; noalias(project(W1, range(i*problem.n,(i+1)*problem.n), range(j*problem.n,(j+1)*problem.n))) += D1(k,i)*D1(k,j) * cache_AtA[k]; } } LOG(DEBUG) << "Initialize matrix W2" << endl; W2.resize(problem.n*(N+1), problem.n*(N+1), false); for (int i=0; i<=N; i++) for (int j=i-2; j<=i+2; j++) { if (j>N || j<0) continue; for (int k=i-2; k<=i+2; k++) { if (k>N || k<0) continue; if (abs(i-k)>2 || abs(j-k)>2) continue; noalias(project(W2, range(i*problem.n,(i+1)*problem.n), range(j*problem.n,(j+1)*problem.n))) += D0(k,i)*D0(k,j)*cache_BtB[k]; } } LOG(DEBUG) << "init QtQ" << endl; QtQ.resize(problem.n*(N+1), problem.n*(N+1), false); for (int i=0; i<=N; i++) for (int j=i-2; j<=i+2; j++) { if (j>N || j<0) continue; for (int k=i-2; k<=i+2; k++) { if (k>N || k<0) continue; if (abs(i-k)>2 || abs(j-k)>2) continue; noalias(project(QtQ, range(i*problem.n,(i+1)*problem.n), range(j*problem.n,(j+1)*problem.n))) += D0(k,i) * D1(k,j) * cache_BtA[k] + D1(k,i) * D0(k,j) * cache_AtB[k]; } } QtQ = W1 + W2 + QtQ; } virtual void init_g() { g.resize(problem.m*(N+1), false); for (int i=0; i<=N; i++) noalias(subrange(g, i*problem.m, (i+1)*problem.m)) = problem.g(i*delta); } public: virtual Real eval_psi(const DenseVector &) = 0; virtual void update_descent(SobolevNorm, const DenseVector &, const Real &scale = 1.) {} virtual void init_descent(SobolevNorm style, const DenseVector &u, const Real &scale = 1.) { SCOPE("DiscretizationBase init_descent"); LOG(DEBUG) << "Initialize caching and matrix Q" << endl; init_caching(u); init_Q(); LOG(DEBUG) << "Initialize S" << endl; type_S = solver::SYM_POS; S.resize(problem.n*(N+1), problem.n*(N+1), false); switch (style) { case NORM_H1: // for (int i=0; i ms(S, slice(0,problem.n,N+1), slice(0,problem.n,N+1)); ms += foo; */ ready: ; } private: virtual void init_caching(const DenseVector &) = 0; protected: std::vector cache_A; std::vector cache_B; std::vector cache_AtA; std::vector cache_BtB; std::vector cache_AtB; std::vector cache_BtA; Real compute_step_width_quadratic(const DenseVector &u, const DenseVector &dir) { const Real p_0 = eval_psi(u); const Real p_1 = eval_psi(u - dir); const Real p_2 = eval_psi(u - 2.*dir); const Real a = (p_2 + p_0 - 2.0 * p_1)/2.0; const Real b = p_1 - p_0 - a; assert(a > 0.); assert(b <= 0.); // TODO: if (std::fabs(a) < PREC::MACHINE_EPS/100000./N) { LOG(WARNING) << "Quadatric step width calculation failed: a = " << a << endl; throw "Minimum seems to be reached to machine precision as no direction of descent was found."; } const Real res = -b/(2.0*a); return res; } Real compute_step_width_local_convex(const DenseVector &u, const DenseVector &dir) { // TODO: dynamic control of minimal/maximal step size and the calculation details const Real MIN_STEP = 1e-10; const Real MAX_STEP = 1e12; const Real STEP_MUL = 8.; const int MAX_ITER = 80; Real step = MIN_STEP; Real cur = eval_psi(u); Real next = eval_psi(u - step*dir); while (step < MAX_STEP && next < cur) { step *= STEP_MUL; cur = next; next = eval_psi(u - step*dir); // LOG(INFO) << "bracketing: " << step << " " << next << endl; } Real a = 0.0; Real b = step; Real vala = eval_psi(u); Real valb = eval_psi(u - b*dir); for (int fine = 0; fine < MAX_ITER; fine++) { Real mid1 = a + (b-a)/3.0; Real mid2 = b - (b-a)/3.0; Real val1 = eval_psi(u - mid1*dir); Real val2 = eval_psi(u - mid2*dir); if (val1 < val2) { b = mid2; valb = val2; } else { a = mid1; vala = val1; } } const Real res = (a+b)/2.0; return res; } }; template struct Discretization : public DiscretizationBase

{ Discretization(const int N, const P &problem) : DiscretizationBase

(N, problem) {} }; template struct Discretization : public DiscretizationBase

{ using DiscretizationBase

::problem; using DiscretizationBase

::N; using DiscretizationBase

::cache_A; using DiscretizationBase

::cache_B; using DiscretizationBase

::cache_AtA; using DiscretizationBase

::cache_BtB; using DiscretizationBase

::cache_AtB; using DiscretizationBase

::cache_BtA; using DiscretizationBase

::delta; using DiscretizationBase

::Q; using DiscretizationBase

::g; Discretization(const int N, const P &problem) : DiscretizationBase

(N, problem) {} private: void init_caching(const DenseVector &) { SCOPE("init_caching linear"); LOG(DEBUG) << "Caching A, B, AtA, AtB, BtB, BtA matrices..." << endl; for (int i=0; i<=N; i++) { cache_A.push_back(problem.A(delta * i)); cache_B.push_back(problem.B(delta * i)); } for (int i=0; i<=N; i++) { cache_AtA.push_back(prod(trans(cache_A[i]), cache_A[i])); cache_BtB.push_back(prod(trans(cache_B[i]), cache_B[i])); } for (int i=0; i<=N; i++) { cache_AtB.push_back(prod(trans(cache_A[i]), cache_B[i])); cache_BtA.push_back(prod(trans(cache_B[i]), cache_A[i])); } } public: Real eval_psi(const DenseVector &u) { DenseVector y = -g; axpy_prod(Q, u, y, false); return inner_prod(y,y)*(problem.T/(N+1))/2.; } void euclidean_gradient(const DenseVector &u, DenseVector &eg) const { DenseVector y = -g; eg.resize(u.size()); axpy_prod(Q, u, y, false); axpy_prod(y, Q, eg, true); } Real compute_step_width(const DenseVector &u, const DenseVector &dir) { const Real sw1 = this->compute_step_width_local_convex(u, dir); const Real sw2 = this->compute_step_width_quadratic(u, dir); const Real p_1 = eval_psi(u - sw1*dir); const Real p_2 = eval_psi(u - sw2*dir); Real res = sw1; if (p_1 > p_2) res = sw2; return res; } }; template struct Discretization : public DiscretizationBase

{ using DiscretizationBase

::problem; using DiscretizationBase

::N; using DiscretizationBase

::cache_A; using DiscretizationBase

::cache_B; using DiscretizationBase

::cache_AtA; using DiscretizationBase

::cache_BtB; using DiscretizationBase

::cache_AtB; using DiscretizationBase

::cache_BtA; using DiscretizationBase

::delta; using DiscretizationBase

::D1; using DiscretizationBase

::Q; using DiscretizationBase

::g; Discretization(const int N, const P &problem) : DiscretizationBase

(N, problem) {} private: void init_caching(const DenseVector &u) { SCOPE("init_caching non-linear"); LOG(DEBUG) << "Caching local A, B, AtA, AtB, BtB, BtA matrices..." << endl; cache_A.clear(); cache_B.clear(); cache_AtA.clear(); cache_BtB.clear(); cache_AtB.clear(); cache_BtA.clear(); DenseVector Du(u.size()); for (int i=0; iinit_descent(style, u, scale); } Real eval_psi(const DenseVector &u) { try { DenseVector Du(u.size()); for (int i=0; icompute_step_width_local_convex(u, dir); } }; template struct SteepestDescent : public Discretization { typedef SteepestDescent self_type; typedef typename SUPP::P P; using Discretization::problem; using Discretization::N; using Discretization::S; using Discretization::type_S; using Discretization::eval_psi; using Discretization::update_descent; using Discretization::init_descent; using Discretization::compute_step_width; using Discretization::euclidean_gradient; using Discretization::u; boost::timer timer; int step; SUPP &supp; // TODO: This is a very primitive smoothing method based on Gauss-Seidel. void smooth(int num = 8) { using ublas::subslice; using ublas::noalias; for (int i=0; i(supp.N, supp.problem), supp(supp) { SCOPE("Constructor SteepestDescent"); step = 0; supp.finalize(); // Default initial function is the vector of constant zero functions. u = ScalarVector(problem.n*(N+1), 0.); } void set_current_estimate(int k, const DenseVector &d) { noalias(subrange(u, k*problem.n, (k+1)*problem.n)) = d; } void get_current_estimate(int k, DenseVector &d) const { d = subrange(u, k*problem.n, (k+1)*problem.n); } void descent(SobolevNorm style, const int STEPS, const Real &FAC = 1., const Real &SCALE = 1.) { SCOPE("descent"); LOG(DEBUG) << string(78, '-') << endl; const int dim = u.size(); DenseVector eg(dim); DenseVector sg(dim); DenseVector sg0(dim); DenseVector dir(dim); #if 0 DenseVector prev_sg0(dim); DenseVector prev_dir(dim); #endif init_descent(style, u, SCALE); LOG(INFO) << "psi = " << eval_psi(u) << endl; LOG(DEBUG) << string(78, '-') << endl; timer.restart(); for (int i=0; i(0., inner_prod(sg0, sg0 - prev_sg0)/inner_prod(prev_sg0, prev_sg0)); // Polak-Ribiere const Real beta = inner_prod(sg0, sg0)/inner_prod(prev_sg0, prev_sg0); dir = sg0 + beta * prev_dir; } prev_sg0 = sg0; prev_dir = dir; #endif // #TODO: /* Real sw = 1.; u -= dir; */ dir /= norm_2(dir); Real sw = compute_step_width(u, dir); u -= FAC*sw*dir; const Real psi = eval_psi(u); ++step; std::cout << "Step " << setw(3) << step << " (" << SOBOLEV_NORM_NAME[style] << "): psi = " << psi << ", sw " << sw << ", len " << len << endl; // if (0 == step % 100) LOG(INFO) << "Step " << setw(3) << step << " (" << SOBOLEV_NORM_NAME[style] << "): psi = " << psi << ", sw " << sw << ", len " << len << endl; // else // LOG(DEBUG) << "Step " << setw(3) << step << " (" << SOBOLEV_NORM_NAME[style] << "): psi = " << psi << ", sw " << sw << ", len " << len << endl; if (std::abs(psi) < PREC::EPS*1e-12) throw MaximumPrecisionReached(); const Real MIN_STEP = 1e-10; const int MIN_COUNT = 5; static int mcnt = 0; if (std::abs(sw) < MIN_STEP) ++mcnt; else mcnt = 0; if (mcnt > MIN_COUNT) throw MinimalStepSize(); } catch (const char *msg) { LOG(WARNING) << "Exception: " << msg << endl; break; } LOG(DEBUG) << "prepare next step" << endl; update_descent(style, u, SCALE); } } }; template void gnuplot_output(const S &sd, std::ostream &out, const Real &offset = 0.) { using std::endl; for (int i=0; i<=sd.N; i++) { // TODO: we assume a uniform time grid const Real t = i*sd.delta + offset; out << t; DenseVector u = subrange(sd.u, i*sd.problem.n, (i+1)*sd.problem.n); for (int j=0; j void gnuplot_input(S &sd, std::istream &in) { for (int k=0; k<=sd.N; k++) { DenseVector dv(sd.problem.n); // TODO: we assume that the first column lists a uniform time grid Real dummy; in >> dummy; for (int i=0; i> dv(i); sd.set_current_estimate(k, dv); } } template struct EmptySupplementaryConditions { typedef PP P; const P &problem; const int N; solver::DefaultSymmetricSolver *solver; EmptySupplementaryConditions(const P &problem, const int N) : problem(problem), N(N) { solver = NULL; } virtual ~EmptySupplementaryConditions() { if (solver != NULL) delete solver; } void project(const DenseVector &u, DenseVector &Pu) { Pu = u; } void update(SparseSymmetricMatrix &S, solver::MatrixType mtype) { if (solver != NULL) delete solver; solver = new solver::DefaultSymmetricSolver(S, mtype); } int solve(DenseVector &x, const DenseVector &b) { solver->solve(x, b); return 0; } void finalize() {} }; template struct SupplementaryConditions { typedef PP P; const P &problem; const int N; typedef std::vector tVI; typedef std::set tSI; typedef std::vector tVM; std::vector supp; std::vector proj; SparseSymmetricMatrix Proj; SupplementaryConditions(const P &problem, const int N) : problem(problem), N(N) { supp.assign(problem.n, SparseRowMatrix(1,N+1)); for (std::vector::iterator it=supp.begin(); it!=supp.end(); ++it) it->clear(); Proj.clear(); Proj = IdentityMatrix((N+1)*problem.n); for (int i=0; iS = &S; } // Solve Pt S P x = Pt b // #TODO: use some appropriate preconditioner // #TODO: use something better than naive CG // #TODO: reduce code duplication int solve(DenseVector &x, const DenseVector &b) { SCOPE("solve general supp"); const SparseSymmetricMatrix &A = *S; // #TODO: const Real EPS = PREC::MACHINE_EPS; const int MAX_IT = 2*A.size1()+A.size1()/10; // std::numeric_limits::max(); const int n = A.size1(); DenseVector bb(b.size()); project(b, bb); using ublas::prod; using ublas::noalias; using ublas::inner_prod; DenseVector Ap(n), r(n), Ax(n); multiply(A, x, Ax); noalias(r) = bb - Ax; DenseVector p = r; Real ns_r = inner_prod(r,r); for (int k=1; k<=MAX_IT; k++) { // LOG(DEBUG) << "CG solver step " << k << ", residual = " << ns_r << endl; if (ns_r <= EPS) { LOG(DEBUG) << "CG solver: " << k << " steps, residual = " << ns_r << endl; return k-1; } multiply(A, p, Ap); const Real alpha = ns_r/inner_prod(p,Ap); noalias(x) += alpha*p; multiply(A, x, Ax); noalias(r) = bb - Ax; const Real tmp = ns_r; ns_r = inner_prod(r,r); const Real beta = ns_r/tmp; p = beta*p + r; } LOG(DEBUG) << "CG solver: " << MAX_IT << " steps (MAX_IT), residual = " << ns_r << endl; return MAX_IT; } private: void multiply(const SparseSymmetricMatrix &A, const DenseVector &u, DenseVector &res) { DenseVector tmp(problem.n*(N+1)); res.resize(problem.n*(N+1), false); project(u, res); ublas::axpy_prod(A, res, tmp, true); project(tmp, res); } }; template struct DirichletSupplementaryConditions { typedef PP P; const P &problem; const int N; typedef std::vector tVI; typedef std::set tSI; solver::DefaultSymmetricSolver *solver; tSI supp; DirichletSupplementaryConditions(const P &problem, const int N) : problem(problem), N(N) { solver = NULL; } virtual ~DirichletSupplementaryConditions() { if (solver != NULL) delete solver; } void fix_value(int i, int j) { assert(0<=i && i *posi) { ++subi; ++posi; } if (posi != supp.end() && int(it.index1()) == *posi) continue; int subj = 0; tSI::const_iterator posj = supp.begin(); for (SparseSymmetricMatrix::const_iterator2 jt=it.begin(); jt!=it.end(); ++jt) { while (posj != supp.end() && int(jt.index2()) > *posj) { ++subj; ++posj; } if (posj != supp.end() && int(jt.index2()) == *posj) continue; S_proj(jt.index1()-subi, jt.index2()-subj) = *jt; } } solver = new solver::DefaultSymmetricSolver(S_proj, mtype); } int solve(DenseVector &x, const DenseVector &b) { // project x and b const int N_orig = (N+1)*problem.n; const int N_proj = N_orig - supp.size(); assert(int(x.size()) == N_orig); assert(int(b.size()) == N_orig); DenseVector x_proj(N_proj); DenseVector b_proj(N_proj); int sub = 0; tSI::const_iterator pos = supp.begin(); for (int i=0; i *pos) { sub++; pos++; } if (pos != supp.end() && i == *pos) continue; x_proj(i-sub) = x(i); b_proj(i-sub) = b(i); } solver->solve(x_proj, b_proj); // now fill in the missing zeros sub = 0; pos = supp.begin(); for (int i=0; i *pos) { sub++; pos++; } if (pos != supp.end() && i == *pos) x(i) = 0.; else x(i) = x_proj(i-sub); } return 0; } void finalize() {} }; template struct IVSupplementaryConditions { typedef PP P; const P &problem; const int N; typedef std::vector tVI; typedef std::set tSI; solver::DefaultSymmetricSolver *solver; tSI supp; SparseSymmetricMatrix Proj; IVSupplementaryConditions(const P &problem, const int N) : problem(problem), N(N), Proj((N+1)*problem.n,(N+1)*problem.n) { SCOPE("constructor IVP supp"); solver = NULL; Proj.clear(); Proj = IdentityMatrix((N+1)*problem.n); for (int i=0; isolve(x_proj, b_proj); project(x_proj, x); return 0; /* // project x and b const int N_orig = (N+1)*problem.n; const int N_proj = N_orig - 2*problem.n; assert(int(x.size()) == N_orig); assert(int(b.size()) == N_orig); DenseVector x_proj(N_proj); DenseVector b_proj(N_proj); noalias(x_proj) = subrange(x, 2*problem.n, N_orig); noalias(b_proj) = subrange(b, 2*problem.n, N_orig); solver->solve(x_proj, b_proj); // now fill in the missing values noalias(ublas::project(x, range(2*problem.n, N_orig))) = x_proj; for (int i=0; i Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __TYPE_HEADER__ #define __TYPE_HEADER__ #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 // bindings #include #include #include #include #include #include #endif typedef double Real; typedef utility::PrecInfo PREC; namespace ublas = boost::numeric::ublas; // namespace lapack = boost::numeric::bindings::lapack; // namespace umf = boost::numeric::bindings::umfpack; typedef ublas::vector DenseVector; typedef ublas::scalar_vector ScalarVector; typedef ublas::matrix DenseMatrix; typedef ublas::compressed_matrix SparseMatrix; typedef ublas::compressed_matrix SparseSymmetricMatrix; typedef ublas::compressed_vector SparseVector; typedef ublas::generalized_vector_of_vector > SparseRowMatrix; typedef ublas::banded_matrix BandedMatrix; typedef ublas::identity_matrix IdentityMatrix; #endif // __TYPE_HEADER__ sgdae/solvers.hxx0000644000175000017500000003466410754367672014347 0ustar msautermsauter/* This file is part of SGDAE, a software to numerically solve differential algebraic equations using a steepest descent method based on Sobolev gradients. You are welcome to contact the authors via e-mail: Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __SOLVER_HXX__ #define __SOLVER_HXX__ namespace solver { using namespace logging; enum MatrixType { UNINITIALIZED = 0, SYM_POS = 2, SYM_INDEF = -2 }; struct ConjugateGradientSolver { typedef ublas::compressed_matrix SparseSymmetricMatrix; typedef ublas::vector DenseVector; const SparseSymmetricMatrix &A; const int n; Real eps; int max_it; ConjugateGradientSolver(const SparseSymmetricMatrix &A, MatrixType type = SYM_POS) : A(A), n(A.size1()), eps(PREC::MACHINE_EPS), max_it(std::numeric_limits::max()) { assert(A.size1() == A.size2()); assert(type == SYM_POS); } int solve(DenseVector &x, const DenseVector &b) { using ublas::prod; using ublas::noalias; using ublas::inner_prod; DenseVector Ap(n), r(n); noalias(r) = b - prod(A,x); DenseVector p = r; Real ns_r = inner_prod(r,r); for (int k=1; k<=max_it; k++) { if (ns_r <= eps) return k-1; Ap = prod(A,p); const Real alpha = ns_r/inner_prod(p,Ap); noalias(x) += alpha*p; noalias(r) = b - prod(A,x); const Real tmp = ns_r; ns_r = inner_prod(r,r); const Real beta = ns_r/tmp; p = beta*p + r; } return max_it; } }; typedef std::vector tVSV; void orthonormalize(const tVSV &v, DenseMatrix &M) { using ublas::inner_prod; using ublas::noalias; using ublas::matrix_column; using ublas::column; assert(v.size() > 0); M.resize(v[0].size(), v.size(), false); typedef matrix_column Column; for (size_t i=0; i 1e-12); col /= norm; } } #ifdef MKL extern "C" { void pardisoinit_(void *pt, int *mtype, int *iparm); void pardiso_(void *pt, int *maxfct, int *mnum, int *mtype, int *phase, int *n, const double *a, const int *ia, const int *ja, int *perm, int *nrhs, int *iparm, int *msglvl, const double *b, double *sol, int *error); void dgetrf_(const int *m, const int *n, double* a, const int *lda, int *ipiv, int *info); void dgetrs_(char const* trans, int const* n, int const* nrhs, double const* a, int const* lda, int const* ipiv, double* b, int const* ldb, int* info); void dgesvd_(char const* jobu, char const* jobvt, int const* m, int const* n, double* a, int const* lda, double* s, double* u, int const* ldu, double* vt, int const* ldvt, double* work, int const* lwork, int* info); } // end extern "C" struct PardisoSolver { typedef std::vector tVI; typedef std::vector tVD; typedef ublas::compressed_matrix SparseSymmetricMatrix; typedef ublas::vector DenseVector; int n, mtype, nrhs, maxfct, mnum, msglvl; const int *ia; const int *ja; const double *a; tVI via; tVI vja; tVD va; int iparm[64]; int *pt[64]; PardisoSolver(const SparseSymmetricMatrix &S, MatrixType type = SYM_POS) { assert(S.size1() == S.size2()); // Initialize diagonal as the pardiso solver expects this. // for (int i=0; i tVD; typedef ublas::matrix FortranMat; typedef ublas::matrix CMat; // ublas bug: FortranMat = SparseRowMatrix triggers failed assertion. CMat tmp(A); FortranMat M(tmp); const char jobu = 'N'; const char jobvt = 'A'; const int m = M.size1(); const int n = M.size2(); double dummy; tVD sv(std::max(1, std::min(m, n))); LOG(DEBUG) << "Initializing singular value decomposition." << endl; DenseMatrix Vt(n,n); int lwork = -1; int info; dgesvd_(&jobu, &jobvt, &m, &n, &M.data()[0], &m, &sv[0], &dummy, &m, &Vt.data()[0], &n, &dummy, &lwork, &info); assert(info == 0); if (info != 0) { LOG(ERROR) << "Problem initializing singular value decomposition." << endl; return 1; } lwork = int(dummy); tVD work(lwork); dgesvd_(&jobu, &jobvt, &m, &n, &M.data()[0], &m, &sv[0], &dummy, &m, &Vt.data()[0], &n, &work[0], &lwork, &info); assert(info == 0); if (info != 0) { LOG(ERROR) << "Problem with singular value calculation." << endl; return 2; } using ublas::noalias; using ublas::outer_prod; using ublas::column; P.clear(); int i = 0; for (tVD::const_iterator it=sv.begin(); it!=sv.end(); ++it,i++) { if (std::fabs(*it) < 1e-12) noalias(P) += outer_prod(column(Vt,i), column(Vt,i)); } for (; i tVI; int n; DenseMatrix &A; tVI ipiv; LUSolver(DenseMatrix &A) : A(A) { assert(A.size1() == A.size2()); n = A.size1(); ipiv.resize(n); int info; dgetrf_(&n, &n, &A.data()[0], &n, &ipiv[0], &info); LOG(DEBUG) << "info dgetrf: " << info << endl; } void solve(DenseVector &x, const DenseVector &b) { assert(b.size() == size_t(n)); x = b; char trans = 'N'; int nrhs = 1; int info; dgetrs_(&trans, &n, &nrhs, &A.data()[0], &n, &ipiv[0], &x.data()[0], &n, &info); LOG(DEBUG) << "info dgetrs: " << info << endl; } }; #elif UMFPACK struct UMFPackSolver { typedef ublas::compressed_matrix, ublas::unbounded_array > umfpack_matrix; umf::symbolic_type Symbolic; umf::numeric_type Numeric; umfpack_matrix A; UMFPackSolver(const SparseMatrix &S, const MatrixType &) : A(S) { assert(A.size1() == A.size2()); umf::symbolic(A, Symbolic); umf::numeric(A, Symbolic, Numeric); } void solve(DenseVector &x, const DenseVector &b) { assert(b.size() == (size_t) A.size1()); x.resize(A.size1(), false); umf::solve(A, x, b, Numeric); } }; typedef UMFPackSolver DefaultSymmetricSolver; #else #warning "We strongly recommend using MKL or UMFPACK for solving the sparse linear systems." #warning "Currently you are compiling this program so that it uses a naive CG implementation." typedef ConjugateGradientSolver DefaultSymmetricSolver; #endif int manual_null_space_projection(const SparseRowMatrix &M, DenseMatrix &P) { SCOPE("manual null space projection"); // using std::cout; // using std::endl; SparseRowMatrix A = M; /* // ublas bug { SparseVector tmp = ublas::column(A, 0); ublas::column(A, 0) = ublas::column(A, 1); ublas::column(A, 1) = tmp; } */ using utility::flabs; using utility::is_zero; using ublas::matrix_row; using ublas::row; using ublas::project; using ublas::range; LOG(DEBUG) << "Gaussian elimination with total pivoting to get free variables." << endl; typedef matrix_row SparseRow; typedef std::set tSI; tSI vfree; for (size_t c=0; c flabs(A(ibest,c))) ibest = i; } } if (nonzero) { // Swap rows if necessary. if (ibest != c) { SparseVector tmp = row(A, ibest); row(A, ibest) = row(A, c); row(A, c) = tmp; } SparseRow crow(row(A, c)); for (size_t i=c+1; i 0) { // Search for the first nonzero element in the last row. SparseRow last(row(A, A.size1()-1)); size_t j = A.size1()-1; for (SparseRow::const_iterator jt=last.begin(); jt!=last.end(); ++jt) if (!is_zero(*jt)) { j = jt.index(); break; } assert(j >= A.size1()-1); for (size_t k=j+1; k0; --i) { SparseRow irow(row(A, i-1)); Real value = 0.; int target = -1; for (SparseRow::const_iterator jt=irow.begin(); jt!=irow.end(); ++jt) { if (is_zero(*jt)) continue; if (vfree.find(jt.index()) == vfree.end() && target == -1) target = jt.index(); else value -= *jt * v(jt.index()); } if (target != -1) v(target) = value/irow(target); } basis.push_back(v); } /* cout << "BASIS: " << endl; for (tVSV::const_iterator it=basis.begin(); it!=basis.end(); ++it) { cout << *it << endl; } */ using ublas::noalias; using ublas::column; using ublas::outer_prod; DenseMatrix ONB; orthonormalize(basis, ONB); P.clear(); for (size_t i=0; i Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #ifndef __UTILITY_HEADER__ #define __UTILITY_HEADER__ #include namespace utility { // #TODO: Ensure support for mpz_float of the gmp library. template struct PrecInfo; // Implementation of precision info type for standard double numbers. template<> struct PrecInfo { static const double EPS; static const double MACHINE_EPS; }; const double PrecInfo::MACHINE_EPS = std::numeric_limits::epsilon(); const double PrecInfo::EPS = std::numeric_limits::epsilon(); #ifdef GMP // GNU multiprecision library. #include #include // Specialization of precision info for the gmpxx multi precision floats. template<> struct PrecInfo { static const int BITS; static const mpf_class EPS; static const mpf_class MACHINE_EPS; static int init(int bits) { mpf_set_default_prec(bits); return bits; } }; const int PrecInfo::BITS = PrecInfo::init(512); const mpf_class PrecInfo::MACHINE_EPS = mpf_class(PrecInfo::MACHINE_EPS); const mpf_class PrecInfo::EPS = mpf_class("1e-13"); #endif // GMP inline double sqr(const double &a) { return a*a; } // BUG: Somewhere inside of the Pardiso solver srand is called with a constant. Therefore the random numbers repeat after each call of the solver. // Workaround: We use the following example implementation of rand/srand. /* POSIX.1-2001 gives the following example of an implementation of rand() and srand(), possibly useful when one needs the same sequence on two different machines. */ static unsigned long next = 1; const unsigned int rand_max = 32767; /* RAND_MAX assumed to be 32767 */ int rand(void) { next = next * 1103515245 + 12345; return((unsigned)(next/65536) % 32768); } void srand(unsigned seed) { next = seed; } double rand_uniform(const double &a=0., const double &b=1.) { return a + double(rand())/rand_max * (b-a); } inline double sign(const double &a) { if (a < 0.) return -1.; if (a > 0.) return 1.; return 0.; } inline double flabs(const double &a) { return fabs(a); } inline bool is_zero(const double &a) { return flabs(a) < PrecInfo::MACHINE_EPS; } } // end namespace utility // addons #include #include namespace boost { namespace assign { template class DataInitializer { public: typedef typename T::value_type value_type; DataInitializer(T &A) { ptr = &A.data()[0]; } void push_back(value_type v) { *ptr++ = v; } template inline list_inserter, value_type> operator =(V v) { return assign::push_back(*this)(v); } private: value_type *ptr; }; template DataInitializer init(T &obj) { DataInitializer myinit(obj); return myinit; } }} struct InvalidInput : public std::exception { const char *msg; InvalidInput(const char *message="Invalid input.") : msg(message) {} virtual const char* what() const throw() { return msg; } }; struct MinimalStepSize : public std::exception { const char *msg; MinimalStepSize(const char *message="Minimal step size reached.") : msg(message) {} virtual const char* what() const throw() { return msg; } }; struct MaximumPrecisionReached : public std::exception { const char *msg; MaximumPrecisionReached(const char *message="Maximum precision was reached.") : msg(message) {} virtual const char* what() const throw() { return msg; } }; #endif // __UTILITY_HEADER__ sgdae/logging.cc0000644000175000017500000000365410754367672014051 0ustar msautermsauter/* This file is part of SGDAE, a software to numerically solve differential algebraic equations using a steepest descent method based on Sobolev gradients. You are welcome to contact the authors via e-mail: Copyright 2005-2008 Manfred Sauter, Robin Nittka. SGDAE is free software distributed under the terms of the revised BSD license as illustrated on . For details consult the accompanying LICENSE.txt file. $Id: $ */ #include "logging.h" namespace logging { tLogger::tLogger() : std::ostream(std::cout.rdbuf()) { tie(MASK_ALL, &null_os); name[DEBUG] = "DEBUG: "; name[INFO] = "INFO: "; name[WARNING] = "WARNING: "; name[ERROR] = "ERROR: "; name[FATAL] = "FATAL: "; } void tLogger::tie(const tLogType type, std::ostream *out) { assert(type < LOG_MASK_END); if (type == MASK_ALL) for (int i=0; i" : "") << *it; if (scope_stack.size()) (*res) << "] "; (*res) << name[type]; return *res; } void tLogger::pushScope(const std::string &scope) { scope_stack.push_back(scope); } void tLogger::popScope() { if (scope_stack.size()) scope_stack.pop_back(); } tNull_ostream tLogger::null_os; tLogger *tLogger::logger = NULL; }; sgdae/config.wsl0000644000175000017500000000043614744137762014101 0ustar msautermsauterMKL := /import/intel/mkl/9.1.023/ OPTIMIZE += -march=athlon64 -ftree-vectorize DEFINES += -DMKL INCLUDES += -I /import/cvs/boost LDFLAGS += -L $(MKL)/lib/32 LDLIBS += $(MKL)/lib/32/libmkl_solver.a $(MKL)/lib/32/libmkl_lapack.a -Wl,-rpath,$(MKL)/lib/32/ -lmkl_ia32 -lguide -lpthread sgdae/config.home0000644000175000017500000000043110754367672014221 0ustar msautermsauterMKL := /opt/intel/mkl/9.1.023 OPTIMIZE += -msse2 -march=athlon64 -mfpmath=sse -ftree-vectorize DEFINES += -DMKL INCLUDES += LDFLAGS += -L $(MKL)/lib/32 LDLIBS += $(MKL)/lib/32/libmkl_solver.a $(MKL)/lib/32/libmkl_lapack.a -Wl,-rpath,$(MKL)/lib/32/ -lmkl_ia32 -lguide -lpthread