double PronyModel(double t, matrix* beta, void *params) { matrix *Ji, *taui; double *p; double J0, J, Jval, tauval; int n, i; p = (double*) params; J0 = *p; /* Pull out all the parameter values */ n = nRows(beta)/2; Ji = CreateMatrix(n, 1); taui = CreateMatrix(n, 1); for(i=0; i<n; i++) { setval(Ji, val(beta, 2*i, 0), i, 0); setval(taui, val(beta, 2*i+1, 0), i, 0); } J = J0; for(i=0; i<n; i++) { Jval = val(Ji, i, 0)*val(Ji, i, 0); tauval = val(taui, i, 0)*val(taui, i, 0); J += Jval * (1-exp(-t/tauval)); } DestroyMatrix(Ji); DestroyMatrix(taui); return J; }
int main(int argc, char **argv) { if (argc < 3) return __exception("Not found input file"); int mRows1 = 0, mCols1 = 0, mRows2 = 0, mCols2 = 0; double ** matrix1 = __loadMatrix(argv[1], &mRows1, &mCols1); double ** matrix2 = __loadMatrix(argv[2], &mRows2, &mCols2); fprintf(stdout, "Matrix N1:\n"); PrintMatrix(matrix1, mRows1, mCols1); fprintf(stdout, "Matrix N2:\n"); PrintMatrix(matrix2, mRows2, mCols2); int zeroCount1 = GetCount(matrix1, mRows1, mCols1, true); int zeroCount2 = GetCount(matrix2, mRows2, mCols2, true); if (zeroCount1 < zeroCount2) fprintf(stdout, "Output matrix N1: %i\n", GetCount(matrix1, mRows1, mCols1, false)); else fprintf(stdout, "Output matrix N2: %i\n", GetCount(matrix2, mRows2, mCols2, false)); DestroyMatrix(matrix1, mRows1, mCols1); DestroyMatrix(matrix2, mRows2, mCols2); system("pause"); return EXIT_SUCCESS; }
/* This program takes up to three arguments. The first is the Peclet number to * use in the calculation. The second is the number of elements to use when * solving the problem, and the third (optional) argument is the filename to * save the solution to. */ int main(int argc, char *argv[]) { double Pe, h; double left = 0; double right = 1; //double right = PI/2; int n; matrix *J, *F, *u, *Jinv, *mesh, *x; /* Parse arguments */ if(argc < 2) { fprintf(stderr, "Too few arguments: exiting.\n"); return 1; } Pe = atof(argv[1]); n = atoi(argv[2]); /* Create a uniform mesh */ mesh = GenerateUniformMesh(left, right, n); /* Use a mesh with these node spacings */ //mesh = ParseMatrix("[.75;.15;.0125;.0125;.0125;.0125;.0125;.0125;.0125;.0125]"); x = MeshXCoords(mesh, left, right); /* All the nodes are equally spaced. */ h = val(mesh, 0, 0); J = AssembleJ(&CreateElementMatrix, mesh, Pe); //J = AssembleJMesh(&testelem, mesh, Pe); F = AssembleF(&CreateElementLoad, mesh, Pe); //F = AssembleFMesh(&testload, mesh, Pe); ApplyBoundaryConditions(J, F, 0, 1); //ApplyBoundaryConditions(J, F, 2, 1); /* Invert the coefficient matrix and premultiply the load vector by it. */ Jinv = CalcInv(J); u = mtxmul(Jinv, F); /* Print out the result */ if(argc == 4) { mtxprntfile(u, argv[3]); } else { mtxprnt(x); puts(""); mtxprnt(u); } /* Clean up the allocated memory */ DestroyMatrix(J); DestroyMatrix(F); DestroyMatrix(u); DestroyMatrix(Jinv); DestroyMatrix(mesh); return 0; }
int main(int argc, char *argv[]) { int i, j, k; double Ti, Mj, percent; vector *T, *M; matrix *t, *Jij, *betaij, *output, *ttmp; /* if(argc < 3) { printf("Usage:\n" "fitcreep: <file> <t1> <t2> ... <tn>\n" "<file>: Filename containing the creep function data.\n" "<t1>: First retardation time\n" "<t2>: Second retardation time\n" "...\n" "<tn>: Nth retardation time.\n"); exit(0); } */ T = linspaceV(333, 363, 10); M = linspaceV(.05, .4, 10); ttmp = linspace(1e-3, 1e3, 1000); t = mtxtrn(ttmp); DestroyMatrix(ttmp); output = CreateMatrix(len(T)*len(M), 2+5); for(i=0; i<len(T); i++) { Ti = valV(T, i); for(j=0; j<len(M); j++) { Mj = valV(M, j); Jij = makedata(t, Ti, Mj); betaij = fitdata(t, Jij); setval(output, Ti, i*len(M)+j, 0); setval(output, Mj, i*len(M)+j, 1); setval(output, val(Jij, 0, 0), i*len(M)+j, 2); for(k=0; k<nRows(betaij); k++) setval(output, pow(val(betaij, k, 0), 2), i*len(T)+j, k+3); DestroyMatrix(Jij); DestroyMatrix(betaij); /* Print the percent done */ percent = (1.*i*len(M)+j)/(len(M)*len(T))*100.; printf("%3.2f %%\r", percent); fflush(stdout); } } DestroyMatrix(t); DestroyVector(T); DestroyVector(M); mtxprntfilehdr(output, "output.csv", "T,M,J0,J1,tau1,J2,tau2\n"); DestroyMatrix(output); return 0; }
/** * Fit the GAB parameters given water activity */ int main(int argc, char *argv[]) { matrix *data, *aw, *Xdb, *tmp0, *tmp1, *beta0, *beta; if(argc != 2) { puts("Usage:"); puts("gab <aw.csv>"); } //data = mtxloadcsv("Andrieu.csv", 0); data = mtxloadcsv(argv[1], 0); /* Get the water activity from column 1 and the moisture content from * column 6. */ aw = ExtractColumn(data, 0); Xdb = ExtractColumn(data, 5); /* Stick the two matricies together and delete any rows that contain * empty values */ tmp0 = AugmentMatrix(aw, Xdb); tmp1 = DeleteNaNRows(tmp0); DestroyMatrix(aw); DestroyMatrix(Xdb); /* Pull the two columns back apart */ aw = ExtractColumn(tmp1, 0); Xdb = ExtractColumn(tmp1, 1); DestroyMatrix(tmp0); DestroyMatrix(tmp1); /* Set up the beta matrix with some initial guesses at the GAB constants. * The solver needs these to be pretty close to the actual values, or it * will fail to converge */ beta0 = CreateOnesMatrix(3, 1); setval(beta0, 6, 0, 0); setval(beta0, .5, 1, 0); setval(beta0, .04, 2, 0); /* Attempt to fit the gab parameters to the supplied data */ beta = fitnlm(&gab, aw, Xdb, beta0); /* Print out the fitted values */ printf("C = %g\nk = %g\nXm = %g\n", val(beta, 0, 0), val(beta, 1, 0), val(beta, 2, 0)); return 0; }
/* Assemble the global coefficient matrix for a non-uniform mesh. The first * argument is a function pointer to the function which creates the element * matrix, and the second is the mesh to be used. */ matrix* AssembleJ(matrix* (*makej)(double, double), matrix* mesh, double Pe) { matrix *J, *j; int n, i; /* Determine the number of elements from the mesh */ n = mtxlen2(mesh); /* Create a blank global matrix */ J = CreateMatrix(n+1, n+1); for(i=0; i<n; i++) { /* Generate the element matrix for the specified element width */ j = makej(Pe, val(mesh, i, 0)); /* Add the values of the element matrix to the global matrix */ addval(J, val(j, 0, 0), i, i); addval(J, val(j, 0, 1), i, i+1); addval(J, val(j, 1, 0), i+1, i); addval(J, val(j, 1, 1), i+1, i+1); /* Clean up */ DestroyMatrix(j); } return J; }
int main(int argc, char **argv) { if (argc < 3) return __exception("Not found input file"); int mRows1 = 0, mCols1 = 0, mRows2 = 0, mCols2 = 0; double ** matrix1 = __loadMatrix(argv[1], &mRows1, &mCols1); double ** matrix2 = __loadMatrix(argv[2], &mRows2, &mCols2); fprintf(stdout, "Matrix N1:\n"); PrintMatrix(matrix1, mRows1, mCols1); fprintf(stdout, "Matrix N2:\n"); PrintMatrix(matrix2, mRows2, mCols2); int S1 = Calculate(matrix1, mRows1, mCols1); int S2 = Calculate(matrix2, mRows2, mCols2); int row, cols; double ** matrix; if(S1 < S2) { matrix = matrix1; row = mRows1; cols = mCols1; } else { matrix = matrix2; row = mRows2; cols = mCols2; } for (int i = 0; i < row; i++) printf("Min element %i line = %3.1f\n", i+1, CalculateRow(matrix, i, cols)); DestroyMatrix(matrix1, mRows1, mCols1); DestroyMatrix(matrix2, mRows2, mCols2); system("pause"); return EXIT_SUCCESS; }
/** * @brief Explicit time integration algorithm (Forward Euler) * * This solver fails horribly if a Neumann boundary condition is imposed. Also, * it may not be entirely stable anyway. * * @param problem The struct containing the problem to solve * @returns A matrix with the solutions at each node */ matrix* LinSolve1DTrans(struct fe1d *problem) { matrix *du, *u; matrix *tmp1, *tmp2, *tmp3, *tmp4; matrix *dresult, *result; solution *prev; /* The solution at the previous time step */ /* Initialize the matricies */ DestroyMatrix(problem->J); DestroyMatrix(problem->dJ); DestroyMatrix(problem->F); AssembleJ1D(problem, NULL); AssembledJ1D(problem, NULL); AssembleF1D(problem, NULL); problem->applybcs(problem); /* Get the previous solution */ prev = FetchSolution(problem, problem->t-1); du = prev->dval; u = prev->val; tmp1 = mtxmulconst(du, problem->dt); tmp2 = mtxadd(u, tmp1); mtxneg(tmp2); tmp3 = mtxmul(problem->J, tmp2); tmp4 = mtxadd(problem->F, tmp3); /* Solve for du/dt */ dresult = SolveMatrixEquation(problem->dJ, tmp4); DestroyMatrix(tmp1); DestroyMatrix(tmp2); DestroyMatrix(tmp3); DestroyMatrix(tmp4); /* Solve for u */ tmp1 = mtxmul(problem->dJ, dresult); mtxneg(tmp1); tmp2 = mtxadd(problem->F, tmp1); result = SolveMatrixEquation(problem->J, tmp2); DestroyMatrix(tmp1); DestroyMatrix(tmp2); StoreSolution(problem, result, dresult); return result; }
/** * Equivalent of the Matlab "regress" function. Solves for the fitting * parameters using matrix algebra. Each column of the X matrix is a set of data * to used to fit a single parameter. To fit a constant, X should contain a * column of ones. * \f[ * \underline{b} = (\underline{\underline{X}}^T\underline{\underline{X}})^{-1} * \underline{\underline{X}}^T\underline{y} * \f] * @param y Column vector of dependent variable values * @param X Matrix of independent variable values, one variable per column * @returns Column matrix of fitted parameters. Each row corresponds to a * column in the supplies X matrix */ matrix* regress(matrix *y, matrix *X) { matrix *Xt, *XtX, *XtXinv, *XtXinvXt, *beta; Xt = mtxtrn(X); XtX = mtxmul(Xt, X); XtXinv = CalcInv(XtX); XtXinvXt = mtxmul(XtXinv, Xt); beta = mtxmul(XtXinvXt, y); DestroyMatrix(Xt); DestroyMatrix(XtX); DestroyMatrix(XtXinv); DestroyMatrix(XtXinvXt); return beta; }
/** * Calculate equilibrium moisture content (Xe) using nonlinear regression. * This function is made obsolete by CalcXeIt * @param initial Row number of the first data point to use in the calculation * @param t Column matrix of time values [s] * @param Xdb Column matrix of moisture contents [kg/kg db] * @param Xe0 Initial guess for Xe. The initial value for kf is hard coded below * @returns Equilibrium moisture content [kg/kg db] * * @see fitnlm XeModel CalcXeIt */ double NCalcXe(int initial, vector *t, vector *Xdb, double Xe0) { double Xe = Xe0; /* Set Xe to the initial guess */ matrix *beta, /* Matrix of fitting values */ *beta0, *Xadj, *tadj; int i; /* Loop index */ /* Print out the starting row */ printf("Starting calculation from row %d.\n", initial); /* Set the initial moisture content */ Xinit = valV(Xdb, initial); beta0 = CreateMatrix(2,1); setval(beta0, Xe0, 0, 0); setval(beta0, 4e-6, 1, 0); /* Make smaller matricies that contain only the "good" data. */ tadj = CreateMatrix(len(Xdb) - initial, 1); Xadj = CreateMatrix(len(Xdb) - initial, 1); for(i=initial; i<len(t); i++) { setval(tadj, valV(t, i), i-initial, 0); setval(Xadj, valV(Xdb, i), i-initial, 0); } /* Actually find Xe */ beta = fitnlm(&XeModel, tadj, Xadj, beta0); Xe = val(beta, 0, 0); //mtxprnt(beta); //mtxprnt(beta0); DestroyMatrix(beta); DestroyMatrix(beta0); DestroyMatrix(tadj); DestroyMatrix(Xadj); return Xe; }
int main(int argc, char **argv) { char *input_filename = NULL, *output_filename = NULL; if (!parse_args(argc, argv, &input_filename, &output_filename)) { help(argv[0]); exit(-1); } FILE *fout = NULL; if (!(fout = fopen(output_filename,"w"))) fout = stdout; Matrix *m1 = NULL, *covariance; m1 = ReadMatrix(input_filename); covariance = Covariance(m1); WriteMatrix(fout, covariance); if (!(fout == stdout)) { printf("Output was written in %s\n", output_filename); fclose(fout); } DestroyMatrix(m1); DestroyMatrix(covariance); return 0; }
LRESULT CALLBACK ScreensaverProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { MATRIX* matrix = GetMatrix(hwndDlg); switch(uMsg) { case WM_NCCREATE: _ShowCursor(0); matrix = CreateMatrix(hwndDlg, ((CREATESTRUCT*)lParam)->cx, ((CREATESTRUCT*)lParam)->cy); if(!matrix) { MessageBox(hwndDlg, L"Ошибка работы скринсейвера", L"Ошибка", MB_OK | MB_ICONSTOP); return 0; } SetMatrix(hwndDlg, matrix); SetTimer(hwndDlg, 0xdeadbeef, ((SPEED_MAX - g_nMatrixSpeed) + SPEED_MIN) * 10, 0); return 1; case WM_TIMER: DecodeMatrix(hwndDlg, matrix); break; case WM_KEYDOWN: if(wParam == VK_ESCAPE) SendMessage(hwndDlg, WM_CLOSE, 0, 0); break; case WM_CLOSE: _ShowCursor(1); DestroyMatrix(matrix); DestroyWindow(hwndDlg); PostQuitMessage(0); break; default: return DefWindowProc(hwndDlg, uMsg, wParam, lParam); } return 0; }
matrix* AssembleF(matrix* (*makef)(double, double), matrix* mesh, double Pe) { matrix *F, *f; int n, i; n = mtxlen2(mesh); F = CreateMatrix(n+1, 1); for(i=0; i<n; i++) { f = makef(Pe, val(mesh, i, 0)); addval(F, val(f, 0, 0), i, 0); addval(F, val(f, 1, 0), i+1, 0); DestroyMatrix(f); } return F; }
matrix* fitdata(matrix *t, matrix *J) { double J0, Jt; J0 = val(J, 0, 0); Jt = val(J, nRows(J)-1, 0); matrix *beta0, *beta; beta0 = CreateMatrix(4, 1); setval(beta0, sqrt( .5*(Jt-J0) ), 0, 0); setval(beta0, sqrt(10), 1, 0); setval(beta0, sqrt( .5*(Jt-J0) ), 2, 0); setval(beta0, sqrt(200), 3, 0); beta = fitnlmP(&PronyModel, t, J, beta0, &J0); DestroyMatrix(beta0); return beta; }
/** * Matlab "polyfit" function. This fits the x-y data to a polynomial of * arbitrary order using the regress function. * @param x Column vector of dependent variable values * @param y Column vector of independent variable values * @param order Degree of the polynomial to fit to * @returns Column matrix of fitted parameters. Element n corresponds to the * coefficient in front of x^n. */ matrix* polyfit(matrix* x, matrix* y, int order) { matrix *X, *beta; int i, j, nelem; X = NULL; nelem = nRows(x); X = CreateMatrix(nelem, order+1); for(i=0; i<=nelem; i++) { for(j=0; j<=order; j++) { setval(X, pow(val(x, i, 0), j), i, j); } } beta = regress(y, X); DestroyMatrix(X); return beta; }
/** * Calculate the equilibrium moisture content. This function determines the best * value of Xe to make a plot of \f$\ln\frac{X-X_e}{X_0-X_e}\f$ vs time linear. * In order to do this, it fits the data to the equation \f$y = a t + b\f$, where * \f$y = \ln(X-X_e)\f$ and \f$b = \ln(X_0-X_e)\f$, and then solves the equation * \f$F(X_e) = b - \ln(X_0-X_e) = 0\f$ using Newton's method. * * This function is made obsolete by CalcXeIt * * @param t Column matrix containing time during drying [s] * @param Xdb Column matrix of moisture content [kg/kg db] * @param Xe0 Initial guess for equilibrium moisture content. * @returns Equilibrium moisture content [kg/kg db] * * @see polyfit CalcXeIt */ double CalcXe(int initial, matrix *t, matrix *Xdb, double Xe0) { double f, df, /* Function values and derivatives */ b, /* Fitting parameters. Only the constant matters */ tol = 1e-10, /* Tolerance for Newton's method */ Xe = Xe0, /* Set Xe to the initial guess */ Xep, /* Previous guess */ X0, /* Initial moisture content */ r2; matrix *beta, /* Matrix of fitting values */ *y, /* Set equal to ln(X - Xe) */ *Xadj, *tadj; int i, /* Loop index */ iter = 0; /* Current iteration */ /* Set the initial moisture content */ X0 = val(Xdb, initial, 0); /* Make smaller matricies that contain only the "good" data. */ tadj = CreateMatrix(nRows(Xdb) - initial, 1); Xadj = CreateMatrix(nRows(Xdb) - initial, 1); for(i=initial; i<nRows(t); i++) { setval(tadj, val(t, i, 0), i-initial, 0); setval(Xadj, val(Xdb, i, 0), i-initial, 0); } /* Actually find Xe */ do { /* Make a y matrix containing ln(Xdb - Xe) */ y = CreateMatrix(nRows(Xadj), 1); for(i=0; i<nRows(Xadj); i++) setval(y, log(val(Xadj, i, 0) - Xe), i, 0); /* Calculate b */ beta = polyfit(tadj, y, 1); r2 = rsquared(tadj, y, beta); b = val(beta, 0, 0); /* Calculate f and df */ f = b - log(X0 - Xe); df = 1/(X0 - Xe); /* Calculate the new value of Xe */ Xep = Xe; Xe = Xe - f/df; /* Clean up */ DestroyMatrix(y); DestroyMatrix(beta); /* Keep track of how many iterations we've gone through */ iter++; /* Print out the current value */ printf("Xe = %g, R^2 = %g\n", Xe, r2); if(Xe < 0) { printf("Failure to converge after %d iterations.\n", iter); return 0; } } while( fabs(Xe - Xep) > tol ); /* Check our value */ /* Print out how many iterations it took to find Xe */ printf("Solution converged after %d iterations.\n", iter); return Xe; }
/** * Calculate the equilibrium moisture content. This algorithm takes an initial * guess for Xe and then fits a linear equation to * \f$\ln\frac{X-X_e}{X_0-X_e}\f$ vs. \f$ t\f$. It then determines the \f$R^2\f$ * value for that set of coefficients and then iteratively improves the fit * using Newton's method. * @param initial Row number of the first data point to use * @param t Vector of time values [s] * @param Xdb Vector of moisture contents [kg/kg db] * @param Xe0 Initial guess for equilibrium moisture content [kg/kg db] * @returns Equilibrium moisture content [kg/kg db] * * @see regress */ double CalcXeIt(int initial, vector *t, vector *Xdb, double Xe0) { int iter = 0, /* Keep track of the number of iterations */ i; /* Loop index */ double Xinit, /* Initial moisture content */ Xe, /* Current guess for Xe */ Xep, /* Previous guess for Xe */ dR, /* First derivative of R^2 with respect to Xe */ d2R, /* Second derivative of R^2 */ kF, tol = 1e-7, /* How close Xe and Xep need to be before we stop */ h = 1e-7, /* Used for numerical differentiation */ m = 2; /* Used to increase the rate of convergence */ matrix *beta, /* Beta value from regress */ *beta_ph, /* Same, but calculated at Xe + h */ *beta_mh, /* Beta at Xe - h */ *tmp_ph, /* Same as beta_ph, but with an extra zero to make rsquared happy */ *tmp, *tmp_mh, *y, /* y values */ *yph, /* Same as y, but at Xe + h */ *ymh, /* y at Xe - h */ *tadj, /* New matrix of t values that starts at the initial row */ *Xadj; /* Same as tadj, but for Xdb */ /* Set the initial moisture content */ Xinit = valV(Xdb, initial); /* Set the first value of Xe to Xe0 */ Xe = Xe0; /* Make smaller matricies that contain only the "good" data. */ tadj = CreateMatrix(len(t) - initial, 1); Xadj = CreateMatrix(len(Xdb) - initial, 1); for(i=initial; i<len(t); i++) { /* In addition to just copying the data, subtract the initial time from * each value to make sure that the intercept for the model goes through * the origin */ setval(tadj, valV(t, i)-valV(t, initial), i-initial, 0); setval(Xadj, valV(Xdb, i), i-initial, 0); } /* Actually find Xe */ do { /* Make a y matrix containing ln((Xdb - Xe)/(X0-Xe)) */ y = CreateMatrix(nRows(Xadj), 1); for(i=0; i<nRows(Xadj); i++) setval(y, log((val(Xadj, i, 0) - Xe)/(Xinit - Xe)), i, 0); /* Calculate the kf parameter */ beta = regress(y, tadj); /* Do the same, but at Xe - h */ ymh = CreateMatrix(nRows(Xadj), 1); for(i=0; i<nRows(Xadj); i++) setval(ymh, log((val(Xadj, i, 0) - Xe-h)/(Xinit - Xe-h)), i, 0); beta_ph = regress(ymh, tadj); /* At Xe + h */ yph= CreateMatrix(nRows(Xadj), 1); for(i=0; i<nRows(Xadj); i++) setval(yph, log((val(Xadj, i, 0) - Xe+h)/(Xinit - Xe+h)), i, 0); beta_mh = regress(yph, tadj); /* Add in a constant parameter of zero to the beta matrix. Do this for * each of the beta matricies we've got. */ tmp_ph = CreateMatrix(2,1); setval(tmp_ph, 0, 0, 0); setval(tmp_ph, val(beta_ph, 0, 0), 1, 0); tmp = CreateMatrix(2,1); setval(tmp, 0, 0, 0); setval(tmp, val(beta, 0, 0), 1, 0); tmp_mh = CreateMatrix(2,1); setval(tmp_mh, 0, 0, 0); setval(tmp_mh, val(beta_mh, 0, 0), 1, 0); /* Calculate f and df */ dR = (rsquared(tadj, yph, tmp_ph) - rsquared(tadj, ymh, tmp_mh))/(2*h); d2R = (rsquared(tadj, yph, tmp_ph) - 2*rsquared(tadj, y, tmp) + rsquared(tadj, ymh, tmp_mh))/(h*h); if(d2R == 0) { printf("Terminating due to division by zero.\n"); break; } /* Calculate the new value of Xe */ Xep = Xe; Xe = Xep + m*dR/d2R; kF = val(tmp, 1, 0); /* Clean up */ DestroyMatrix(y); DestroyMatrix(yph); DestroyMatrix(ymh); DestroyMatrix(beta); DestroyMatrix(tmp_ph); DestroyMatrix(tmp); DestroyMatrix(tmp_mh); /* Keep track of how many iterations we've gone through */ iter++; /* Print out the current value */ printf("Xe = %g\r", Xe); /* If Xe ever goes negative, admit defeat. */ if(Xe < 0) { printf("Failure to converge after %d iterations.\n", iter); return Xe; } } while( fabs(Xe - Xep) > tol ); /* Check our value */ /* Print out how many iterations it took to find Xe */ printf("Solution converged after %d iterations.\n", iter); printf("kF = %g\n", kF); return Xe; }
/** * Implicit time integration solver. (Nonlinear version) * Works with both backward difference * integration (BD) and the trapazoid rule (TR). In either case, the algorithm * is supposed to be unconditionally stable. This function only solves the * problem at the next time step. In order to solve for the desired variables * over the entire time domain, call this function repeatedly. * * The time deriviative is calculated using the following formula: * y'(t1) = a/dt * [y(t1) - y(t0)] + b*y'(t0) * Here, t1 is the time at the current time step and t0 is at the previous one. * The variables a and b are constants that determine which algorithm is used * to approximate the derivative. For a=1, b=0, backward difference is used, * and for a=2, b=-1, trapazoid rule is used. * * @param problem Finite element problem to solve * @param guess Initial guess at the solution for the next time step. If this * is not supplied (NULL), then the solution is predicted based on the * previous time steps. * @returns Pointer to a matrix of the calculated values. This can be safely * disregarded since the matrix is also stored in the finite element * problem structure. */ matrix* NLinSolve1DTransImp(struct fe1d *problem, matrix *guess) { int iter = 0; /* Current iteration number */ int maxiter = 5000; /* Maximum allowed iterations before terminating */ /* Constants that determine the integration algorithm. If a=1 and b=0, then * the backward difference method is being used. For the trapazoid rule, * a=2, and b=-1. */ int a, b; solution *prev; /* Solution at the previous time step */ matrix *J, *F, *R; /* Jacobian matrix and the residuals matrix */ matrix *tmp1, *tmp2; /* Temporary matricies */ matrix *u, *du, *dx; matrix *dguess; /* Time derivative of the guess */ /* Use BD */ a = 1; b = 0; /* Note: This solver doesn't work at all with anything but backward * difference for time integration. The linear one doesn't either, but it * at least contains some code for it. */ /* Get the previous solution */ prev = FetchSolution(problem, problem->t-1); du = prev->dval; u = prev->val; /* Predict the next solution if an initial guess isn't supplied. */ if(!guess) guess = PredictSolnO0(problem); dx = NULL; //exit(0); do { iter++; /* Quit if we've reached the maximum number of iterations */ if(iter == maxiter) break; problem->guess = guess; /* Delete the matricies from the previous iteration */ DestroyMatrix(problem->J); DestroyMatrix(problem->dJ); DestroyMatrix(problem->F); /* Delete the dx matrix from the previous iteration. */ if(dx) DestroyMatrix(dx); /* Initialize the matricies */ AssembleJ1D(problem, guess); AssembledJ1D(problem, guess); AssembleF1D(problem, guess); //problem->guess = NULL; /* Calculate the Jacobian matrix */ tmp1 = mtxmulconst(problem->dJ, a/problem->dt); J = mtxadd(tmp1, problem->J); DestroyMatrix(tmp1); /* Calculate the load vector */ tmp1 = mtxmulconst(problem->dJ, a/problem->dt); tmp2 = mtxmul(tmp1, u); F = mtxadd(problem->F, tmp2); DestroyMatrix(tmp1); DestroyMatrix(tmp2); /* Apply boundary conditions. */ DestroyMatrix(problem->J); DestroyMatrix(problem->F); problem->J = J; problem->F = F; problem->applybcs(problem); /* Calculate the residual vector */ tmp1 = mtxmul(problem->J, guess); mtxneg(tmp1); R = mtxadd(problem->F, tmp1); DestroyMatrix(tmp1); //mtxprnt(problem->J); //puts(""); //mtxprnt(problem->dJ); //puts(""); //mtxprnt(problem->F); /* Solve for dx */ dx = SolveMatrixEquation(J, R); /* Delete the residual matrix and the Jacobian matrix*/ DestroyMatrix(R); /* Add the change in the unknowns to the guess from the previous * iteration */ tmp1 = mtxadd(guess, dx); DestroyMatrix(guess); guess = tmp1; #ifdef VERBOSE_OUTPUT /* Print the current iteration number to the console. */ printf("\rIteration %d", iter); fflush(stdout); // Flush the output buffer. #endif } while(!CheckConverg1D(problem, dx)); /* Delete the final dx matrix */ DestroyMatrix(dx); if(iter==maxiter) { printf("Nonlinear solver failed to converge. " "Maximum number of iterations reached.\n" "Failed to calculate solution at time step %d of %d\n" "Exiting.\n", problem->t, problem->maxsteps); printf("Current step size: %g\n", problem->dt); PrintSolution(problem, problem->t-1); printf("Current guess:\n"); PrintGuess(problem, guess); exit(0); } #ifdef VERBOSE_OUTPUT if(iter == -1) /* If we've determined the matrix to be singular by calculating the * determinant, then output the appropriate error message. */ printf("\rSingular matrix.\n"); else if(iter == maxiter) /* If the solver didn't find a solution in the specified number of * iterations, then say so. */ printf("\rNonlinear solver failed to converge. " "Maximum number of iterations reached.\n"); else /* Print out the number of iterations it took to converge * successfully. */ printf("\rNonlinear solver converged after %d iterations.\n", iter); #endif /* Solve for the time derivative of the result. */ dguess = CalcTimeDerivative(problem, guess); StoreSolution(problem, guess, dguess); /* Delete the time derivative of the pervious solution to save memory. */ //DeleteTimeDeriv(prev); return guess; }
/** * Nonlinear finite element solver. (1D version) * * This does all the same stuff as the linear * solver (assembling the global matricies), but utilizes an initial guess to * calculate them. It then iterates using Newton's method and updates this * guess at each iteration. * * @param problem The struct containing the problem to solve * @param guess The initial guess * * @returns A matrix with the solution at each node */ matrix* NLinSolve1D(struct fe1d *problem, matrix *guess) { matrix *dx; /* How much to update the guess by */ matrix *newguess; //int rows = (2*problem->mesh->nelemx+1)*(2*problem->mesh->nelemy+1); int rows = problem->nrows; int iter = 0; int maxiter = 500; if(!guess) { guess = CreateMatrix(rows*problem->nvars, 1); } do { iter++; if(problem->J) DestroyMatrix(problem->J); if(problem->F) DestroyMatrix(problem->F); AssembleJ1D(problem, guess); problem->F = CreateMatrix(rows*problem->nvars, 1); //AssembleF(problem, guess); problem->applybcs(problem); //if(!CalcDeterminant(problem->J)) { // iter = -1; // break; //} /* ToDo: Write this function! */ CalcResidual1D(problem, guess); dx = SolveMatrixEquation(problem->J, problem->R); newguess = mtxadd(guess, dx); DestroyMatrix(guess); guess = newguess; /* Quit if we've reached the maximum number of iterations */ if(iter == maxiter) break; /* Print the current iteration number to the console. */ printf("\rIteration %d", iter); fflush(stdout); // Flush the output buffer. } while(!CheckConverg1D(problem, dx)); /* ^^ Also quit if the dx variable is small enough. */ if(iter == -1) /* If we've determined the matrix to be singular by calculating the * determinant, then output the appropriate error message. */ printf("\rSingular matrix.\n"); else if(iter == maxiter) /* If the solver didn't find a solution in the specified number of * iterations, then say so. */ printf("\rNonlinear solver failed to converge. " "Maximum number of iterations reached.\n"); else /* Print out the number of iterations it took to converge * successfully. */ printf("\rNonlinear solver converged after %d iterations.\n", iter); return guess; }
/** * Implicit time integration solver. (Linear version) * * Works with both backward difference * integration (BD) and the trapazoid rule (TR). In either case, the algorithm * is supposed to be unconditionally stable. This function only solves the * problem at the next time step. In order to solve for the desired variables * over the entire time domain, call this function repeatedly. * * The time deriviative is calculated using the following formula: * y'(t1) = a/dt * [y(t1) - y(t0)] + b*y'(t0) * Here, t1 is the time at the current time step and t0 is at the previous one. * The variables a and b are constants that determine which algorithm is used * to approximate the derivative. For a=1, b=0, backward difference is used, * and for a=2, b=-1, trapazoid rule is used. * * @param problem The problem to solve * @returns A matrix with the solutions at each node */ matrix* LinSolve1DTransImp(struct fe1d *problem) { /* Constants that determine the integration algorithm. If a=1 and b=0, then * the backward difference method is being used. For the trapazoid rule, * a=2, and b=-1. */ int a, b; matrix *u, /* Used to store the solution at the previous time step */ *du; /* Derivative of u at the previous time step */ /* Used to store intermediate calculations */ matrix *tmp1, *tmp2, *tmp3, *tmp4; matrix *dresult, *result; solution *prev; /* Solution at previous time step */ /* Use BD for testing */ a = 1; b = 0; /* Initialize the matricies */ DestroyMatrix(problem->J); DestroyMatrix(problem->dJ); DestroyMatrix(problem->F); AssembleJ1D(problem, NULL); AssembledJ1D(problem, NULL); AssembleF1D(problem, NULL); /* Get the previous solution */ prev = FetchSolution(problem, problem->t-1); du = prev->dval; u = prev->val; /* Calculate the matrix to be multiplied by the unknown vector */ tmp1 = mtxmulconst(problem->dJ, a/problem->dt); tmp2 = mtxadd(tmp1, problem->J); DestroyMatrix(tmp1); /* Determine the right hand side of the equation. The if statement is there * so that this function can be used for both TR and BD, but not waste an * extra step multiplying by 0 for BD. */ tmp1 = mtxmulconst(problem->dJ, a/problem->dt); tmp3 = mtxmul(tmp1, u); DestroyMatrix(tmp1); if(b) { tmp1 = mtxmulconst(problem->dJ, b); tmp4 = mtxmul(tmp1, du); mtxneg(tmp4); DestroyMatrix(tmp1); tmp1 = mtxadd(tmp3, tmp4); DestroyMatrix(tmp4); DestroyMatrix(tmp3); } else { tmp1 = tmp3; } tmp3 = mtxadd(tmp1, problem->F); DestroyMatrix(tmp1); /* Apply boundary conditions here so that any Dirchlet boundary conditions * are imposed properly for the transient solver. Doing it here, rather than * above guarantees that the specified value on the boundaries doesn't * change randomly. */ DestroyMatrix(problem->J); DestroyMatrix(problem->F); problem->J = tmp2; problem->F = tmp3; problem->applybcs(problem); /* Solve the matrix equation to find the nodal values */ result = SolveMatrixEquation(problem->J, problem->F); /* Solve for the time derivative of the result. */ dresult = CalcTimeDerivative(problem, result); StoreSolution(problem, result, dresult); /* Delete the time derivative of the pervious solution to save memory. */ DeleteTimeDeriv(prev); return result; }
void LoadBalance3d(Mesh *mesh){ int n,p,k,v,f; int nprocs = mesh->nprocs; int procid = mesh->procid; int **EToV = mesh->EToV; double **VX = mesh->GX; double **VY = mesh->GY; double **VZ = mesh->GZ; if(!procid) printf("Root: Entering LoadBalance\n"); int Nverts = mesh->Nverts; int *Kprocs = BuildIntVector(nprocs); /* local number of elements */ int Klocal = mesh->K; /* find number of elements on all processors */ MPI_Allgather(&Klocal, 1, MPI_INT, Kprocs, 1, MPI_INT, MPI_COMM_WORLD); /* element distribution -- cumulative element count on processes */ idxtype *elmdist = idxmalloc(nprocs+1, "elmdist"); elmdist[0] = 0; for(p=0;p<nprocs;++p) elmdist[p+1] = elmdist[p] + Kprocs[p]; /* list of element starts */ idxtype *eptr = idxmalloc(Klocal+1, "eptr"); eptr[0] = 0; for(k=0;k<Klocal;++k) eptr[k+1] = eptr[k] + Nverts; /* local element to vertex */ idxtype *eind = idxmalloc(Nverts*Klocal, "eind"); for(k=0;k<Klocal;++k) for(n=0;n<Nverts;++n) eind[k*Nverts+n] = EToV[k][n]; /* weight per element */ idxtype *elmwgt = idxmalloc(Klocal, "elmwgt"); for(k=0;k<Klocal;++k) elmwgt[k] = 1.; /* weight flag */ int wgtflag = 0; /* number flag (1=fortran, 0=c) */ int numflag = 0; /* ncon = 1 */ int ncon = 1; /* nodes on element face */ int ncommonnodes = 3; /* number of partitions */ int nparts = nprocs; /* tpwgts */ float *tpwgts = (float*) calloc(Klocal, sizeof(float)); for(k=0;k<Klocal;++k) tpwgts[k] = 1./(float)nprocs; float ubvec[MAXNCON]; for (n=0; n<ncon; ++n) ubvec[n] = UNBALANCE_FRACTION; int options[10]; options[0] = 1; options[PMV3_OPTION_DBGLVL] = 7; options[PMV3_OPTION_SEED] = 0; int edgecut; idxtype *part = idxmalloc(Klocal, "part"); MPI_Comm comm; MPI_Comm_dup(MPI_COMM_WORLD, &comm); ParMETIS_V3_PartMeshKway (elmdist, eptr, eind, elmwgt, &wgtflag, &numflag, &ncon, &ncommonnodes, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); int **outlist = (int**) calloc(nprocs, sizeof(int*)); double **xoutlist = (double**) calloc(nprocs, sizeof(double*)); double **youtlist = (double**) calloc(nprocs, sizeof(double*)); double **zoutlist = (double**) calloc(nprocs, sizeof(double*)); int *outK = (int*) calloc(nprocs, sizeof(int)); int *inK = (int*) calloc(nprocs, sizeof(int)); MPI_Request *inrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *outrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *xinrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *xoutrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *yinrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *youtrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *zinrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); MPI_Request *zoutrequests = (MPI_Request*) calloc(nprocs, sizeof(MPI_Request)); for(k=0;k<Klocal;++k) ++outK[part[k]]; /* get count of incoming elements from each process */ MPI_Alltoall(outK, 1, MPI_INT, inK, 1, MPI_INT, MPI_COMM_WORLD); /* count totals on each process */ int * newKprocs = BuildIntVector(nprocs); MPI_Allreduce(outK, newKprocs, nprocs, MPI_INT, MPI_SUM, MPI_COMM_WORLD); int totalinK = 0; for(p=0;p<nprocs;++p){ totalinK += inK[p]; } int **newEToV = BuildIntMatrix(totalinK, Nverts); double **newVX = BuildMatrix(totalinK, Nverts); double **newVY = BuildMatrix(totalinK, Nverts); double **newVZ = BuildMatrix(totalinK, Nverts); int cnt = 0; for(p=0;p<nprocs;++p){ MPI_Irecv(newEToV[cnt], Nverts*inK[p], MPI_INT, p, 666+p, MPI_COMM_WORLD, inrequests+p); MPI_Irecv(newVX[cnt], Nverts*inK[p], MPI_DOUBLE, p, 1666+p, MPI_COMM_WORLD, xinrequests+p); MPI_Irecv(newVY[cnt], Nverts*inK[p], MPI_DOUBLE, p, 2666+p, MPI_COMM_WORLD, yinrequests+p); MPI_Irecv(newVZ[cnt], Nverts*inK[p], MPI_DOUBLE, p, 3666+p, MPI_COMM_WORLD, zinrequests+p); cnt = cnt + inK[p]; } for(p=0;p<nprocs;++p){ int cnt = 0; outlist[p] = BuildIntVector(Nverts*outK[p]); xoutlist[p] = BuildVector(Nverts*outK[p]); youtlist[p] = BuildVector(Nverts*outK[p]); zoutlist[p] = BuildVector(Nverts*outK[p]); for(k=0;k<Klocal;++k) if(part[k]==p){ for(v=0;v<Nverts;++v){ outlist[p][cnt] = EToV[k][v]; xoutlist[p][cnt] = VX[k][v]; youtlist[p][cnt] = VY[k][v]; zoutlist[p][cnt] = VZ[k][v]; ++cnt; } } MPI_Isend(outlist[p], Nverts*outK[p], MPI_INT, p, 666+procid, MPI_COMM_WORLD, outrequests+p); MPI_Isend(xoutlist[p], Nverts*outK[p], MPI_DOUBLE, p, 1666+procid, MPI_COMM_WORLD, xoutrequests+p); MPI_Isend(youtlist[p], Nverts*outK[p], MPI_DOUBLE, p, 2666+procid, MPI_COMM_WORLD, youtrequests+p); MPI_Isend(zoutlist[p], Nverts*outK[p], MPI_DOUBLE, p, 3666+procid, MPI_COMM_WORLD, zoutrequests+p); } MPI_Status *instatus = (MPI_Status*) calloc(nprocs, sizeof(MPI_Status)); MPI_Status *outstatus = (MPI_Status*) calloc(nprocs, sizeof(MPI_Status)); MPI_Waitall(nprocs, inrequests, instatus); MPI_Waitall(nprocs, xinrequests, instatus); MPI_Waitall(nprocs, yinrequests, instatus); MPI_Waitall(nprocs, zinrequests, instatus); MPI_Waitall(nprocs, outrequests, outstatus); MPI_Waitall(nprocs, xoutrequests, outstatus); MPI_Waitall(nprocs, youtrequests, outstatus); MPI_Waitall(nprocs, zoutrequests, outstatus); if(mesh->GX!=NULL){ DestroyMatrix(mesh->GX); DestroyMatrix(mesh->GY); DestroyMatrix(mesh->GZ); DestroyIntMatrix(mesh->EToV); } mesh->GX = newVX; mesh->GY = newVY; mesh->GZ = newVZ; mesh->EToV = newEToV; mesh->K = totalinK; for(p=0;p<nprocs;++p){ if(outlist[p]){ free(outlist[p]); free(xoutlist[p]); free(youtlist[p]); free(zoutlist[p]); } } free(outK); free(inK); free(inrequests); free(outrequests); free(xinrequests); free(xoutrequests); free(yinrequests); free(youtrequests); free(zinrequests); free(zoutrequests); free(instatus); free(outstatus); }
void DestroySystem(System *a) { DestroyMatrix(a->Position); DestroyMatrix(a->Velocity); DestroyMatrix(a->Velocity_xsph); DestroyMatrix(a->Velocity_min); DestroyMatrix(a->dvdt); DestroyMatrix(a->av); DestroyMatrix(a->dwdx); DestroyMatrix(a->dwdx_r); DestroyMatrix(a->dummyVelocity); DestroyMatrix(a->dummyAcceleration); DestroyMatrix(a->fluctuation); DestroyMatrix(a->temps); DestroyMatrix(a->DistanceNeighbors); DestroyMatrix((double **)a->Neighbors); free(a->Energy); free(a->hsml); free(a->Pressure); free(a->itype); free(a->rho); free(a->rho_min); free(a->drhodt); free(a->mass); free(a->i_pair); free(a->j_pair); free(a->rij2); free(a->w); free(a->w_r); free(a->i_inflow); free(a->gradVxx); free(a->gradVxy); free(a->gradVyx); free(a->gradVyy); free(a->strainRatexx); free(a->strainRatexy); free(a->strainRateyx); free(a->strainRateyy); free(a->deviatoricxx); free(a->deviatoricxy); free(a->deviatoricyx); free(a->deviatoricyy); free(a->divV); free(a->KinVisc); free(a->numberDensity); free(a->dummyPressure); free(a->vorticity); free(a); cleanup(); }