Changeset 8512
- Timestamp:
- Mar 1, 2016 9:15:21 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Python/src/tests_jmodelica/files/Modelica/Singular.mo
r8065 r8512 205 205 (sin(x*y*z)+z) = 0; 206 206 end NonLinear5; 207 208 model NoMinimumNormSolution 209 Real x,y,z,v; 210 parameter Real a11 = 1; 211 parameter Real a12 = 2; 212 parameter Real a13 = 3; 213 parameter Real a21 = 1; 214 parameter Real a22 = 1; 215 parameter Real a23 = 1; 216 Real a31(start=0); 217 Real a32(start=0); 218 Real a33(start=0); 219 parameter Real b[3] = {1,2,3}; 220 equation 221 a33=a31+a32; 222 a33=a31^2+a32^2; 223 a33=a31-a32; 224 a11*x+a12*y+a13*z = b[1]; 225 a21*x+a22*y+a23*z = b[2]; 226 a31*x+a32*y+a33*z = b[3]; 227 der(v) = time; 228 end NoMinimumNormSolution; 207 229 208 230 end Singular; -
trunk/Python/src/tests_jmodelica/simulation/test_assimulo_interface_fmi.py
r8507 r8512 621 621 compile_fmu("Singular.NonLinear4", file_name) 622 622 compile_fmu("Singular.NonLinear5", file_name) 623 compile_fmu("Singular.NoMinimumNormSolution", file_name) 623 624 624 625 @testattr(stddist = True) … … 749 750 nose.tools.assert_almost_equal(res["z"][0] ,0.000000000) 750 751 nose.tools.assert_almost_equal(res["z"][-1] ,-1.000000000) 752 753 @testattr(stddist = True) 754 def test_no_valid_minimum_norm_sol(self): 755 model = load_fmu("NoMinimumNormSolution.fmu", log_level=3) 756 model.set("_log_level", 3) 757 model.set_log_level(log_level) 758 nose.tools.assert_raises(FMUException, model.initialize) 751 759 752 760 class Test_FMI_ODE_CS_2: -
trunk/RuntimeLibrary/src/jmi/jmi_block_solver.c
r8507 r8512 28 28 #include <string.h> 29 29 #include <math.h> 30 31 #include <sundials/sundials_math.h> 32 #include <sundials/sundials_direct.h> 33 #include <nvector/nvector_serial.h> 34 #include <kinsol/kinsol_direct.h> 35 #include <kinsol/kinsol_impl.h> 36 #include <sundials/sundials_dense.h> 30 37 31 38 #include "jmi_log.h" … … 56 63 jmi_block_solver_options_t* options, 57 64 void* problem_data){ 65 int i; 58 66 jmi_block_solver_t* block_solver = (jmi_block_solver_t*)calloc(1, sizeof(jmi_block_solver_t)); 59 67 if(!block_solver) { … … 74 82 75 83 block_solver->dx=(jmi_real_t*)calloc(n,sizeof(jmi_real_t));; /**< \brief Work vector for the seed vector */ 84 85 block_solver->f_scale = N_VNew_Serial(n); 86 block_solver->scale_update_time = -1.0; 87 if(n>0) { 88 block_solver->J = NewDenseMat(n ,n); 89 block_solver->J_scale = NewDenseMat(n ,n); 90 } 76 91 77 92 block_solver->res = (jmi_real_t*)calloc(n,sizeof(jmi_real_t)); … … 84 99 block_solver->max = (jmi_real_t*)calloc(n,sizeof(jmi_real_t)); 85 100 block_solver->nominal = (jmi_real_t*)calloc(n,sizeof(jmi_real_t)); 101 block_solver->residual_nominal = (jmi_real_t*)calloc(n+1,sizeof(jmi_real_t)); 102 block_solver->residual_heuristic_nominal = (jmi_real_t*)calloc(n+1,sizeof(jmi_real_t)); 86 103 block_solver->initial = (jmi_real_t*)calloc(n,sizeof(jmi_real_t)); 87 104 block_solver->start_set = (jmi_real_t*)calloc(n,sizeof(jmi_real_t)); … … 97 114 98 115 block_solver->cur_time = 0; 116 block_solver->using_max_min_scaling_flag = 0; /* Not using max/min scaling */ 117 118 /* Initial equation scaling is 1.0 */ 119 N_VConst_Serial(1.0,block_solver->f_scale); 120 121 /* Make sure that residual_nominals and heuristic nominals always have values */ 122 for(i=0; i<n; i++) { 123 block_solver->residual_nominal[i] = 1.0; 124 block_solver->residual_heuristic_nominal[i] = 1.0; 125 } 126 99 127 switch(options->solver) { 100 128 case JMI_KINSOL_SOLVER: { … … 196 224 free(block_solver->dx); 197 225 226 N_VDestroy_Serial(block_solver->f_scale); 227 if(block_solver->n > 0) { 228 DestroyMat(block_solver->J); 229 DestroyMat(block_solver->J_scale); 230 } 231 198 232 free(block_solver->res); 199 233 free(block_solver->dres); … … 205 239 free(block_solver->max); 206 240 free(block_solver->nominal); 241 free(block_solver->residual_nominal); 242 free(block_solver->residual_heuristic_nominal); 207 243 free(block_solver->initial); 208 244 free(block_solver->value_references); … … 297 333 block_solver->F(block_solver->problem_data,real_vrs,block_solver->res,JMI_BLOCK_VALUE_REFERENCE); 298 334 block_solver->F(block_solver->problem_data,block_solver->start_set,block_solver->res,JMI_BLOCK_START_SET); 335 jmi_setup_f_residual_scaling(block_solver); 299 336 300 337 for (i=0;i<block_solver->n;i++) { … … 710 747 } 711 748 749 /* 750 Compute appropriate equation scaling and function tolerance based on Jacobian J, 751 nominal values (block->nominal) and current point (block->x). 752 Store result in block->f_scale. 753 */ 754 void jmi_update_f_scale(jmi_block_solver_t *block) { 755 int i, N = block->n; 756 realtype curtime = block->cur_time; 757 realtype* scale_ptr = 0; 758 jmi_block_solver_options_t* bsop = block->options; 759 int use_scaling_flag = bsop->residual_equation_scaling_mode; 760 realtype tol = bsop->res_tol; 761 762 block->scale_update_time = curtime; 763 block->force_rescaling = 0; 764 765 if(bsop->residual_equation_scaling_mode != jmi_residual_scaling_none) { 766 /* Zero out the scales initially if we're modify this. */ 767 N_VConst_Serial(0,block->f_scale); 768 } 769 770 scale_ptr = N_VGetArrayPointer(block->f_scale); 771 772 /* Form scaled Jacobian as needed for automatic scaling and condition number checking*/ 773 if (bsop->residual_equation_scaling_mode == jmi_residual_scaling_auto || 774 bsop->residual_equation_scaling_mode == jmi_residual_scaling_aggressive_auto || 775 bsop->residual_equation_scaling_mode == jmi_residual_scaling_full_jacobian_auto || 776 bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid || 777 bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) 778 { 779 for (i = 0; i < N; i++) { 780 int j; 781 /* column scaling is formed by max(abs(nominal), abs(actual_value)) */ 782 realtype xscale = RAbs(block->nominal[i]); 783 realtype x = RAbs(block->x[i]); 784 realtype* col_ptr; 785 realtype* scaled_col_ptr; 786 if(x < xscale) x = xscale; 787 if(x < tol) x = tol; 788 col_ptr = DENSE_COL(block->J, i); 789 scaled_col_ptr = DENSE_COL(block->J_scale, i); 790 791 /* row scaling is product of Jac entry and column scaling */ 792 for (j = 0; j < N; j++) { 793 realtype dres = col_ptr[j]; 794 realtype fscale; 795 fscale = dres * x; 796 scaled_col_ptr[j] = fscale; 797 scale_ptr[j] = MAX(scale_ptr[j], RAbs(fscale)); 798 } 799 } 800 } 801 802 /* put in manual non-zero scales in hybrid & manual cases */ 803 if( (bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) 804 || (bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid)) { 805 for(i = 0; i < N; i++) { 806 if(block->residual_nominal[i] != 0) { 807 scale_ptr[i] = block->residual_nominal[i]; 808 } 809 } 810 } 811 812 if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_auto 813 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_aggressive_auto 814 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_full_jacobian_auto 815 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid) { 816 block->using_max_min_scaling_flag = 0; /* NOT using max/min scaling */ 817 /* check that scaling factors have reasonable magnitude */ 818 for(i = 0; i < N; i++) { 819 if(scale_ptr[i] == 0.0) { 820 jmi_log_node(block->log, logInfo, "JacobianZeroRow", 821 "The derivatives for <residual: %d> are all equal 0. Using heuristic residual nominals for scaling in <block: %s>", i, block->label); 822 scale_ptr[i] = block->residual_heuristic_nominal[i]; 823 } else if(scale_ptr[i] < 1/bsop->max_residual_scaling_factor) { 824 int j, maxInJacIndex = 0; 825 realtype **jac = block->J_scale->cols; 826 realtype maxInJac = RAbs(jac[0][i]); 827 block->using_max_min_scaling_flag = 1; /* Using maximum scaling, singular Jacobian? */ 828 for(j = 0; j < N; j++) { 829 if(RAbs(maxInJac) < RAbs(jac[j][i])) { 830 maxInJac = jac[j][i]; 831 maxInJacIndex = j; 832 } 833 } 834 835 scale_ptr[i] = bsop->max_residual_scaling_factor; 836 jmi_log_node(block->log, logWarning, "MaxScalingUsed", "Poor scaling in <block: %s>. " 837 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).", 838 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(block->J, i, maxInJacIndex) ,maxInJac); 839 } 840 else if(scale_ptr[i] > 1/bsop->min_residual_scaling_factor) { 841 int j, maxInJacIndex = 0; 842 realtype **jac = block->J_scale->cols; 843 realtype maxInJac = RAbs(jac[0][i]); 844 /* Likely not a problem: solver->using_max_min_scaling_flag = 1; -- Using minimum scaling */ 845 for(j = 0; j < N; j++) { 846 if(RAbs(maxInJac) < RAbs(jac[j][i])) { 847 maxInJac = jac[j][i]; 848 maxInJacIndex = j; 849 } 850 } 851 852 if (scale_ptr[i] > block->residual_heuristic_nominal[i]/bsop->min_residual_scaling_factor) { 853 scale_ptr[i] = bsop->min_residual_scaling_factor/block->residual_heuristic_nominal[i]; 854 jmi_log_node(block->log, logWarning, "MinScalingUsed", "Poor scaling in <block: %s>. " 855 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).", 856 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(block->J, i, maxInJacIndex) ,maxInJac); 857 } else { 858 scale_ptr[i] = 1/scale_ptr[i]; 859 jmi_log_node(block->log, logWarning, "MinScalingExceeded", "Poor scaling in <block: %s> but will allow it based on structure of block. " 860 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).", 861 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(block->J, i, maxInJacIndex) ,maxInJac); 862 } 863 } 864 else 865 scale_ptr[i] = 1/scale_ptr[i]; 866 } 867 868 if (block->callbacks->log_options.log_level >= 4) { 869 jmi_log_node_t outer = jmi_log_enter_fmt(block->log, logInfo, "ResidualScalingUpdated", "<block:%s>", block->label); 870 if (block->callbacks->log_options.log_level >= 5) { 871 jmi_log_node_t inner = jmi_log_enter_vector_(block->log, outer, logInfo, "scaling"); 872 realtype* res = scale_ptr; 873 for (i=0;i<N;i++) jmi_log_real_(block->log, 1/res[i]); 874 jmi_log_leave(block->log, inner); 875 } 876 jmi_log_leave(block->log, outer); 877 } 878 } else if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) { 879 for(i = 0; i < N; i++) { 880 scale_ptr[i] = 1/scale_ptr[i]; 881 } 882 /* Scaling is not updated */ 883 if (block->callbacks->log_options.log_level >= 4) { 884 jmi_log_node_t outer = jmi_log_enter_fmt(block->log, logInfo, "ResidualScalingUpdated", "<block:%s>", block->label); 885 if (block->callbacks->log_options.log_level >= 5) { 886 jmi_log_node_t inner = jmi_log_enter_vector_(block->log, outer, logInfo, "scaling"); 887 realtype* res = scale_ptr; 888 for (i=0;i<N;i++) jmi_log_real_(block->log, 1/res[i]); 889 jmi_log_leave(block->log, inner); 890 } 891 jmi_log_leave(block->log, outer); 892 } 893 } 894 return; 895 } 896 897 void jmi_setup_f_residual_scaling(jmi_block_solver_t *block) { 898 jmi_block_solver_options_t* bsop = block->options; 899 int i, N = block->n; 900 realtype* dummy = 0; 901 902 /* Read manual scaling from annotations and propagated nominal values for 903 * residuals and put them in residual_nominal & scale_ptr*/ 904 if (bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual || 905 bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid) 906 { 907 block->F(block->problem_data,dummy, block->residual_nominal, JMI_BLOCK_EQUATION_NOMINAL); 908 for (i = 0; i < N; i++) { 909 if(block->residual_nominal[i] != 0.0) { 910 if(block->residual_nominal[i] < 1/bsop->max_residual_scaling_factor) { 911 block->residual_nominal[i] = 1/bsop->max_residual_scaling_factor; 912 jmi_log_node(block->log, logWarning, "MaxScalingUsed", "Using maximum scaling factor in <block: %s>, " 913 "<equation: %I> since specified residual nominal is too small.", block->label, i); 914 } 915 else if(block->residual_nominal[i] > 1/bsop->min_residual_scaling_factor) { 916 block->residual_nominal[i] = 1/bsop->min_residual_scaling_factor; 917 jmi_log_node(block->log, logWarning, "MinScalingUsed", "Using minimal scaling factor in <block: %s>, " 918 "<equation: %I> since specified residual nominal is too big.", block->label, i); 919 } 920 } 921 else if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) { 922 block->residual_nominal[i] = 1.0; 923 } 924 } 925 } 926 927 block->F(block->problem_data,dummy, block->residual_heuristic_nominal, JMI_BLOCK_EQUATION_NOMINAL_AUTO); 928 block->F(block->problem_data,dummy, block->residual_heuristic_nominal, JMI_BLOCK_EQUATION_NOMINAL); 929 for (i = 0; i < N; i++) { 930 if (block->residual_heuristic_nominal[i] == 0.0) { 931 /* TODO: This information could be used to see that the system is structually singular */ 932 block->residual_heuristic_nominal[i] = 1.0; 933 } 934 } 935 } 936 937 double* jmi_solver_get_f_scales(jmi_block_solver_t* block) { 938 return N_VGetArrayPointer(block->f_scale); 939 } 940 941 double calculate_scaled_residual_norm(double* residual, double *f_scale, int n) { 942 double scaledRes, norm = 0; 943 int i; 944 for(i=0; i<n; i++) { 945 scaledRes = residual[i]*f_scale[i]; 946 norm = norm>= RAbs(scaledRes)?norm:RAbs(scaledRes); 947 } 948 return norm; 949 } 950 -
trunk/RuntimeLibrary/src/jmi/jmi_block_solver.h
r8507 r8512 28 28 #include "jmi_log.h" 29 29 #include <time.h> 30 30 #include <sundials/sundials_math.h> 31 #include <sundials/sundials_direct.h> 32 #include <nvector/nvector_serial.h> 33 #include <kinsol/kinsol_direct.h> 34 #include <kinsol/kinsol_impl.h> 35 #include <sundials/sundials_dense.h> 31 36 32 37 /** \brief Evaluation modes for the residual function.*/ … … 350 355 void jmi_block_solver_init_default_options(jmi_block_solver_options_t* op); 351 356 357 /** \brief Update function scaling based on Jacobian information */ 358 void jmi_update_f_scale(jmi_block_solver_t *block); 359 360 /**< \brief Retrieve residual scales used in solver */ 361 double* jmi_solver_get_f_scales(jmi_block_solver_t* block); 362 363 /**< \brief Setup residual scaling */ 364 void jmi_setup_f_residual_scaling(jmi_block_solver_t *block); 365 366 /** \brief Calculate scaled residual max norm */ 367 double calculate_scaled_residual_norm(double* residual, double *f_scale, int n); 368 352 369 /** \brief Check and log illegal iv inputs */ 353 370 int jmi_check_and_log_illegal_iv_input(jmi_block_solver_t* block, double* ivs, int N); -
trunk/RuntimeLibrary/src/jmi/jmi_block_solver_impl.h
r8313 r8512 37 37 jmi_string_t label; 38 38 39 N_Vector f_scale; /**< \brief Work vector for scaling of f */ 40 realtype scale_update_time; /**< \brief The last time when f scale was updated */ 39 41 int n; /**< \brief The number of iteration variables */ 40 42 jmi_real_t* x; /**< \brief Work vector for the real iteration variables */ 41 43 jmi_real_t* last_accepted_x; /**< \brief Work vector for the real iteration variables holding the last accepted vales by the integrator */ 44 DlsMat J; /**< \brief The Jacobian matrix */ 45 DlsMat J_scale; /**< \brief Jacobian matrix scaled with xnorm for used for fnorm calculation */ 46 int using_max_min_scaling_flag; /**< \brief A flag indicating if either the maximum scaling is used of the minimum */ 42 47 43 48 jmi_real_t* dx; /**< \brief Work vector for the seed vector */ … … 66 71 jmi_real_t* max; /**< \brief Max values for iteration variables */ 67 72 jmi_real_t* nominal; /**< \brief Nominal values for iteration variables */ 73 jmi_real_t* residual_nominal; /**< \brief Nominals values for residual variables */ 74 jmi_real_t* residual_heuristic_nominal; /**< \brief Heuristic nominals values for residual variables */ 68 75 jmi_real_t* initial; /**< \brief Initial values for iteration variables */ 69 76 jmi_real_t* start_set; /**< \brief If the start value is specified for the iteration variables */ 70 77 71 78 int jacobian_variability; /**< \brief Variability of Jacobian coefficients: JMI_CONSTANT_VARIABILITY 72 79 JMI_PARAMETER_VARIABILITY, JMI_DISCRETE_VARIABILITY, JMI_CONTINUOUS_VARIABILITY */ -
trunk/RuntimeLibrary/src/jmi/jmi_kinsol_solver.c
r8435 r8512 48 48 static int jmi_kin_lsetup(struct KINMemRec * kin_mem); 49 49 50 /* Update residual scales based on jacobian information */ 51 static void jmi_update_f_scale(jmi_block_solver_t *block); 50 /* Only call directly after jmi_update_f_scale */ 51 static void jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(jmi_block_solver_t *block); 52 53 static realtype jmi_calculate_jacobian_condition_number(jmi_block_solver_t * block); 52 54 53 55 /* Calculate matrix vector product vv = M*v or vv = M^T*v */ … … 174 176 /* Test if output is OK (no -1.#IND) */ 175 177 n = NV_LENGTH_S(ff); 176 ret = jmi_check_and_log_illegal_residual_output(block, f, y, solver->residual_heuristic_nominal ,n);178 ret = jmi_check_and_log_illegal_residual_output(block, f, y, block->residual_heuristic_nominal ,n); 177 179 178 180 /* record information for Brent search */ … … 702 704 int i, info, N = block->n; 703 705 realtype tol = solver->kin_stol; 704 realtype *scale_ptr = N_VGetArrayPointer( solver->kin_f_scale);706 realtype *scale_ptr = N_VGetArrayPointer(block->f_scale); 705 707 if(block->options->residual_equation_scaling_mode != 0) { 706 708 for(i = 0; i < N; i++){ 707 709 int j; 708 realtype* scaled_col_ptr = DENSE_COL( solver->J_scale, i);709 realtype* col_ptr = DENSE_COL( solver->J, i);710 realtype* scaled_col_ptr = DENSE_COL(block->J_scale, i); 711 realtype* col_ptr = DENSE_COL(block->J, i); 710 712 realtype xscale = RAbs(block->nominal[i]); 711 713 realtype x = RAbs(block->x[i]); … … 717 719 } 718 720 } else { 719 DenseCopy( solver->J, solver->J_scale);720 } 721 dgetrf_( &N, &N, solver->J_scale->data, &N, solver->lapack_iwork, &info);721 DenseCopy(block->J, block->J_scale); 722 } 723 dgetrf_( &N, &N, block->J_scale->data, &N, solver->lapack_iwork, &info); 722 724 if(info > 0) { 723 725 jmi_log_node(block->log, logWarning, "SingularJacobian", … … 725 727 } 726 728 else { 727 dgecon_(&norm, &N, solver->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info);729 dgecon_(&norm, &N, block->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info); 728 730 729 731 if(tol * Jcond < UNIT_ROUNDOFF) { … … 809 811 jmi_kinsol_solver_t* solver = block->solver; 810 812 struct KINMemRec* kin_mem = solver->kin_mem; 811 realtype* residual_scaling_factors = N_VGetArrayPointer( solver->kin_f_scale);813 realtype* residual_scaling_factors = N_VGetArrayPointer(block->f_scale); 812 814 jmi_log_t *log = block->log; 813 815 clock_t t = jmi_block_solver_start_clock(block); … … 1037 1039 jmi_log_fmt(block->log, node, logInfo, " <max_iter_no_jacobian: %d>", block->options->max_iter_no_jacobian); 1038 1040 jmi_log_fmt(block->log, node, logInfo, " <active_bounds_mode: %d>", block->options->active_bounds_mode); 1041 jmi_log_fmt(block->log, node, logInfo, " <start_from_last_integrator_step: %d>", block->options->start_from_last_integrator_step); 1039 1042 jmi_log_leave(block->log, node); 1040 1043 … … 1490 1493 int i,j,k; 1491 1494 realtype **JTJ_c = solver->JTJ->cols; 1492 realtype **jac = solver->J->cols;1495 realtype **jac = block->J->cols; 1493 1496 int N = block->n; 1494 1497 realtype * uscale_data = N_VGetArrayPointer(solver->kin_y_scale); 1495 realtype * fscale_data = N_VGetArrayPointer( solver->kin_f_scale);1498 realtype * fscale_data = N_VGetArrayPointer(block->f_scale); 1496 1499 1497 1500 for (i=0;i<N;i++) { … … 1547 1550 } 1548 1551 1552 /* Call this function directly after jmi_update_f_scale */ 1553 static void jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(jmi_block_solver_t *block) { 1554 1555 jmi_kinsol_solver_t* solver = block->solver; 1556 int i, N = block->n; 1557 jmi_block_solver_options_t* bsop = block->options; 1558 int use_scaling_flag = bsop->residual_equation_scaling_mode; 1559 realtype tol = solver->kin_stol; 1560 realtype* scale_ptr = N_VGetArrayPointer(block->f_scale); 1561 1562 if (block->using_max_min_scaling_flag && !solver->J_is_singular_flag) { 1563 realtype cond = jmi_calculate_jacobian_condition_number(block); 1564 1565 jmi_log_node(block->log, logInfo, "Regularization", 1566 "Calculated condition number in <block: %s>. Regularizing if <cond: %E> is greater than <regtol: %E>", block->label, cond, solver->kin_reg_tol); 1567 if (cond > solver->kin_reg_tol) { 1568 if(N > 1 && solver->handling_of_singular_jacobian_flag == JMI_REGULARIZATION) { 1569 int info; 1570 jmi_kinsol_reg_matrix(block); 1571 dgetrf_( &block->n, &block->n, solver->JTJ->data, &block->n, solver->lapack_ipiv, &info); 1572 } 1573 solver->J_is_singular_flag = 1; 1574 } 1575 } 1576 1577 1578 /* estimate condition number of the scaled jacobian 1579 and scale function tolerance with it. */ 1580 if((N > 1) && bsop->check_jac_cond_flag){ 1581 realtype* scaled_col_ptr; 1582 char norm = 'I'; 1583 double Jnorm = 1.0, Jcond = 1.0; 1584 int info; 1585 if(use_scaling_flag) { 1586 for(i = 0; i < N; i++){ 1587 int j; 1588 scaled_col_ptr = DENSE_COL(block->J_scale, i); 1589 for(j = 0; j < N; j++){ 1590 scaled_col_ptr[j] = scaled_col_ptr[j] * scale_ptr[j]; 1591 } 1592 } 1593 } else { 1594 DenseCopy(block->J, block->J_scale); 1595 } 1596 1597 dgetrf_( &N, &N, block->J_scale->data, &N, solver->lapack_iwork, &info); 1598 if(info > 0) { 1599 jmi_log_node(block->log, logWarning, "SingularJacobian", 1600 "Singular Jacobian detected when checking condition number in <block:%s>. Solver may fail to converge.", block->label); 1601 } 1602 else { 1603 dgecon_(&norm, &N, block->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info); 1604 1605 if(tol * Jcond < UNIT_ROUNDOFF) { 1606 jmi_log_node_t node = jmi_log_enter_fmt(block->log, logWarning, "IllConditionedJacobian", 1607 "<JacobianInverseConditionEstimate:%E> Solver may fail to converge in <block: %s>.", Jcond, block->label); 1608 if (block->callbacks->log_options.log_level >= 4) { 1609 jmi_log_reals(block->log, node, logWarning, "ivs", N_VGetArrayPointer(solver->kin_y), block->n); 1610 } 1611 jmi_log_leave(block->log, node); 1612 1613 } 1614 else { 1615 jmi_log_node(block->log, logInfo, "JacobianCondition", 1616 "<JacobianInverseConditionEstimate:%E>", Jcond); 1617 } 1618 } 1619 } 1620 } 1549 1621 1550 1622 /* Estimate condition number utilizing dgecon from LAPACK*/ … … 1558 1630 1559 1631 /* Copy Jacobian to factorization matrix */ 1560 DenseCopy( solver->J, solver->J_LU);1632 DenseCopy(block->J, solver->J_LU); 1561 1633 /* Perform LU factorization to be used with dgecon */ 1562 1634 dgetrf_(&N, &N, solver->J_LU->data, &N, solver->lapack_ipiv, &info); … … 1567 1639 1568 1640 /* Compute infinity norm of J to be used with dgecon */ 1569 J_norm = dlange_(&norm, &N, &N, solver->J->data, &N, solver->lapack_work);1641 J_norm = dlange_(&norm, &N, &N, block->J->data, &N, solver->lapack_work); 1570 1642 1571 1643 /* Compute reciprocal condition number */ … … 1597 1669 return 0; 1598 1670 } 1599 SetToZero( solver->J);1671 SetToZero(block->J); 1600 1672 1601 1673 /* Evaluate Jacobian */ 1602 ret = kin_dF(N, solver->kin_y, kin_mem->kin_fval, solver->J, block, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2);1674 ret = kin_dF(N, solver->kin_y, kin_mem->kin_fval, block->J, block, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2); 1603 1675 solver->updated_jacobian_flag = 1; /* The Jacobian is current */ 1604 1676 … … 1607 1679 jmi_log_node(block->log, logWarning, "CompressedJacobianEvaluation", "Failed to evaluate Jacobian using compression. Will try full finite differences."); 1608 1680 /* Try if it helps with full finite differences with possibility to step in other direction */ 1609 ret = kin_dF(N, solver->kin_y, kin_mem->kin_fval, solver->J, block, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2);1681 ret = kin_dF(N, solver->kin_y, kin_mem->kin_fval, block->J, block, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2); 1610 1682 solver->has_compression_setup_flag = TRUE; 1611 1683 } … … 1626 1698 } 1627 1699 1628 if(block->force_rescaling) 1700 if(block->force_rescaling) { 1629 1701 jmi_update_f_scale(block); 1702 jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(block); 1703 } 1630 1704 1631 1705 return 0; … … 1646 1720 denom = jmi_kinsol_calc_v1twwv2(kin_mem->kin_pp,kin_mem->kin_pp,solver->kin_y_scale); 1647 1721 /* work_vector = Jac * step */ 1648 jmi_kinsol_calc_Mv( solver->J, 0, kin_mem->kin_pp, solver->work_vector);1722 jmi_kinsol_calc_Mv(block->J, 0, kin_mem->kin_pp, solver->work_vector); 1649 1723 1650 1724 /* work_vector = (ResidualDelta - Jac * step) unless below update tolerance */ … … 1659 1733 1660 1734 for(j=0; j < N; j++) { 1661 realtype *jacCol_j = solver->J->cols[j];1735 realtype *jacCol_j = block->J->cols[j]; 1662 1736 double tempj = Ith(kin_mem->kin_pp, j)*Ith(solver->kin_y_scale,j)*Ith(solver->kin_y_scale,j); 1663 1737 for(i = 0; i < N; i++) { … … 1680 1754 jmi_log_fmt(block->log, node,logInfo, "Update denominator <step_norm: %g>", denom); 1681 1755 #endif 1682 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", solver->J->data, N, N);1756 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", block->J->data, N, N); 1683 1757 } 1684 1758 jmi_log_leave(block->log, node); … … 1699 1773 1700 1774 /* work_vector = Jac * step */ 1701 jmi_kinsol_calc_Mv( solver->J, 0, kin_mem->kin_pp, solver->work_vector);1775 jmi_kinsol_calc_Mv(block->J, 0, kin_mem->kin_pp, solver->work_vector); 1702 1776 1703 1777 /* work_vector = (ResidualDelta - Jac * step) unless below update tolerance */ … … 1715 1789 double denom = 0; 1716 1790 for(j=0; j < N; j++) { 1717 denom += Ith(kin_mem->kin_pp, j)*Ith(kin_mem->kin_pp, j)* solver->J->cols[j][i]*solver->J->cols[j][i];1791 denom += Ith(kin_mem->kin_pp, j)*Ith(kin_mem->kin_pp, j)*block->J->cols[j][i]*block->J->cols[j][i]; 1718 1792 } 1719 1793 Ith(solver->work_vector2,i) = denom; … … 1721 1795 1722 1796 for(j=0; j < N; j++) { 1723 realtype *jacCol_j = solver->J->cols[j];1797 realtype *jacCol_j = block->J->cols[j]; 1724 1798 for(i = 0; i < N; i++) { 1725 1799 if( Ith(solver->work_vector2,i) >= UNIT_ROUNDOFF) { … … 1739 1813 jmi_log_reals(block->log, node,logInfo, "res_JacStep", N_VGetArrayPointer(solver->work_vector), N); 1740 1814 #endif 1741 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", solver->J->data, N, N);1815 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", block->J->data, N, N); 1742 1816 } 1743 1817 jmi_log_leave(block->log, node); … … 1759 1833 /* work_vector2 = res_diff */ 1760 1834 N_VLinearSum(1, solver->last_residual, -1, b, solver->work_vector); 1761 N_VProd(solver->work_vector, solver->kin_f_scale, solver->work_vector);1762 N_VProd(solver->work_vector, solver->kin_f_scale, solver->work_vector);1835 N_VProd(solver->work_vector, block->f_scale, solver->work_vector); 1836 N_VProd(solver->work_vector, block->f_scale, solver->work_vector); 1763 1837 /* work_vector2 = res_diff^T*f_scale^2*Jac */ 1764 jmi_kinsol_calc_Mv( solver->J, TRUE, solver->work_vector, solver->work_vector2);1838 jmi_kinsol_calc_Mv(block->J, TRUE, solver->work_vector, solver->work_vector2); 1765 1839 1766 1840 /* denom1 = step^T.*kin_y_scale^2*step */ 1767 1841 denom1 = jmi_kinsol_calc_v1twwv2(kin_mem->kin_pp,kin_mem->kin_pp,solver->kin_y_scale); 1768 1842 /* work_vector = Jac * step */ 1769 jmi_kinsol_calc_Mv( solver->J, 0, kin_mem->kin_pp, solver->work_vector);1843 jmi_kinsol_calc_Mv(block->J, 0, kin_mem->kin_pp, solver->work_vector); 1770 1844 /* denom2 = res_diff^T.*kin_f_scale^2*Jac*step */ 1771 1845 denom2 = 0; 1772 1846 for(i = 0; i < N; i++) { 1773 denom2 += -(Ith(b,i) - Ith(solver->last_residual,i))*Ith( solver->kin_f_scale,i)*Ith(solver->kin_f_scale,i)*Ith(solver->work_vector,i);1847 denom2 += -(Ith(b,i) - Ith(solver->last_residual,i))*Ith(block->f_scale,i)*Ith(block->f_scale,i)*Ith(solver->work_vector,i); 1774 1848 } 1775 1849 1776 1850 for(j=0; j < N; j++) { 1777 realtype *jacCol_j = solver->J->cols[j];1851 realtype *jacCol_j = block->J->cols[j]; 1778 1852 double tempj1 = Ith(kin_mem->kin_pp,j)*Ith(solver->kin_y_scale,j)*Ith(solver->kin_y_scale,j)/denom1; 1779 1853 double tempj2 = Ith(solver->work_vector2,j)/denom2; … … 1797 1871 jmi_log_fmt(block->log, node,logInfo, "Update denominator <denom2: %g>", denom2); 1798 1872 #endif 1799 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", solver->J->data, N, N);1873 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", block->J->data, N, N); 1800 1874 } 1801 1875 jmi_log_leave(block->log, node); … … 1815 1889 clock_t t = jmi_block_solver_start_clock(block); 1816 1890 1817 DenseCopy( solver->J, solver->J_LU); /* make a copy of the Jacobian that will be used for LU factorization */1891 DenseCopy(block->J, solver->J_LU); /* make a copy of the Jacobian that will be used for LU factorization */ 1818 1892 1819 1893 /* Equillibrate if corresponding option is set */ … … 1875 1949 "Will try to find the minimum norm solution in <block: %s>", block->label); 1876 1950 SetToZero(solver->J_sing); 1877 DenseCopy( solver->J, solver->J_sing);1951 DenseCopy(block->J, solver->J_sing); 1878 1952 } else { 1879 1953 /* Error */ … … 1950 2024 int i; 1951 2025 jmi_log_node_t node = jmi_log_enter_fmt(block->log, logInfo, "AggressiveResidualScalingUpdate", "Updating f_scale aggressively"); 1952 N_VScale(1.0, solver->kin_f_scale, solver->work_vector);2026 N_VScale(1.0, block->f_scale, solver->work_vector); 1953 2027 jmi_update_f_scale(block); 2028 jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(block); 1954 2029 for(i=0; i<block->n; i++) { 1955 Ith( solver->kin_f_scale, i) = Ith(solver->kin_f_scale, i) > Ith( solver->work_vector, i)? Ith( solver->work_vector, i):Ith(solver->kin_f_scale, i);2030 Ith(block->f_scale, i) = Ith(block->f_scale, i) > Ith( solver->work_vector, i)? Ith( solver->work_vector, i):Ith(block->f_scale, i); 1956 2031 } 1957 2032 if (block->callbacks->log_options.log_level >= 4) { … … 1959 2034 if (block->callbacks->log_options.log_level >= 5) { 1960 2035 jmi_log_node_t inner = jmi_log_enter_vector_(block->log, outer, logInfo, "scaling"); 1961 realtype* res = N_VGetArrayPointer( solver->kin_f_scale);2036 realtype* res = N_VGetArrayPointer(block->f_scale); 1962 2037 for (i=0;i<N;i++) jmi_log_real_(block->log, 1/res[i]); 1963 2038 jmi_log_leave(block->log, inner); … … 1993 2068 } 1994 2069 1995 kin_mem->kin_sJpnorm = N_VWL2Norm(b, solver->kin_f_scale);2070 kin_mem->kin_sJpnorm = N_VWL2Norm(b,block->f_scale); 1996 2071 solver->sJpnorm = kin_mem->kin_sJpnorm; 1997 N_VProd(b, solver->kin_f_scale, x);1998 N_VProd(x, solver->kin_f_scale, x);2072 N_VProd(b, block->f_scale, x); 2073 N_VProd(x, block->f_scale, x); 1999 2074 2000 2075 kin_mem->kin_sfdotJp = N_VDotProd(kin_mem->kin_fval, x); … … 2014 2089 */ 2015 2090 2016 jmi_kinsol_calc_Mv( solver->J, TRUE, x, solver->gradient);2091 jmi_kinsol_calc_Mv(block->J, TRUE, x, solver->gradient); 2017 2092 } 2018 2093 if(solver->use_steepest_descent_flag) { … … 2023 2098 } 2024 2099 else if(solver->J_is_singular_flag) { 2025 realtype** jac = solver->J->cols;2100 realtype** jac = block->J->cols; 2026 2101 if (N == 1) { 2027 2102 xd[0] = block->nominal[0] * 0.1 *((bd[0] > 0)?1:-1) * ((jac[0][0] > 0)?1:-1); … … 2030 2105 /* solve the regularized problem */ 2031 2106 int i,j; 2032 realtype * fscale_data = N_VGetArrayPointer( solver->kin_f_scale);2107 realtype * fscale_data = N_VGetArrayPointer(block->f_scale); 2033 2108 realtype gnorm;/*gradient norm*/ 2034 2109 … … 2120 2195 2121 2196 if((block->callbacks->log_options.log_level >= 6)) { 2122 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", solver->J->data, N, N);2197 jmi_log_real_matrix(block->log, node, logInfo, "jacobian", block->J->data, N, N); 2123 2198 jmi_log_reals(block->log, node, logInfo, "rhs", xd, N); 2124 2199 } … … 2203 2278 2204 2279 /* recalculate sJpnorm */ 2205 jmi_kinsol_calc_Mv( solver->J, FALSE, x, b);2206 sJpnorm = N_VWL2Norm(b, solver->kin_f_scale);2280 jmi_kinsol_calc_Mv(block->J, FALSE, x, b); 2281 sJpnorm = N_VWL2Norm(b,block->f_scale); 2207 2282 /* update sJpnorm and sfdotJp for Kinsol */ 2208 2283 kin_mem->kin_sJpnorm = sJpnorm; … … 2219 2294 block->step_calc_time += jmi_block_solver_elapsed_time(block, t); 2220 2295 return 0; 2221 }2222 2223 double* jmi_kinsol_solver_get_f_scales(jmi_kinsol_solver_t* solver) {2224 return N_VGetArrayPointer(solver->kin_f_scale);2225 }2226 2227 static void jmi_setup_f_residual_scaling(jmi_block_solver_t *block) {2228 jmi_block_solver_options_t* bsop = block->options;2229 jmi_kinsol_solver_t* solver = block->solver;2230 int i, N = block->n;2231 realtype* dummy = 0;2232 2233 /* Read manual scaling from annotations and propagated nominal values for2234 * residuals and put them in residual_nominal & scale_ptr*/2235 if (bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual ||2236 bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid)2237 {2238 block->F(block->problem_data,dummy, solver->residual_nominal, JMI_BLOCK_EQUATION_NOMINAL);2239 for (i = 0; i < N; i++) {2240 if(solver->residual_nominal[i] != 0.0) {2241 if(solver->residual_nominal[i] < 1/bsop->max_residual_scaling_factor) {2242 solver->residual_nominal[i] = 1/bsop->max_residual_scaling_factor;2243 jmi_log_node(block->log, logWarning, "MaxScalingUsed", "Using maximum scaling factor in <block: %s>, "2244 "<equation: %I> since specified residual nominal is too small.", block->label, i);2245 }2246 else if(solver->residual_nominal[i] > 1/bsop->min_residual_scaling_factor) {2247 solver->residual_nominal[i] = 1/bsop->min_residual_scaling_factor;2248 jmi_log_node(block->log, logWarning, "MinScalingUsed", "Using minimal scaling factor in <block: %s>, "2249 "<equation: %I> since specified residual nominal is too big.", block->label, i);2250 }2251 }2252 else if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) {2253 solver->residual_nominal[i] = 1.0;2254 }2255 }2256 }2257 2258 block->F(block->problem_data,dummy, solver->residual_heuristic_nominal, JMI_BLOCK_EQUATION_NOMINAL_AUTO);2259 block->F(block->problem_data,dummy, solver->residual_heuristic_nominal, JMI_BLOCK_EQUATION_NOMINAL);2260 for (i = 0; i < N; i++) {2261 if (solver->residual_heuristic_nominal[i] == 0.0) {2262 /* TODO: This information could be used to see that the system is structually singular */2263 solver->residual_heuristic_nominal[i] = 1.0;2264 }2265 }2266 }2267 2268 /*2269 Compute appropriate equation scaling and function tolerance based on Jacobian J,2270 nominal values (block->nominal) and current point (block->x).2271 Store result in solver->kin_f_scale.2272 */2273 static void jmi_update_f_scale(jmi_block_solver_t *block) {2274 jmi_kinsol_solver_t* solver = block->solver;2275 int i, N = block->n;2276 realtype tol = solver->kin_stol;2277 realtype curtime = block->cur_time;2278 realtype* scale_ptr = 0;2279 jmi_block_solver_options_t* bsop = block->options;2280 int use_scaling_flag = bsop->residual_equation_scaling_mode;2281 2282 2283 solver->kin_scale_update_time = curtime;2284 block->force_rescaling = 0;2285 2286 if(bsop->residual_equation_scaling_mode != jmi_residual_scaling_none) {2287 /* Zero out the scales initially if we're modify this. */2288 N_VConst_Serial(0,solver->kin_f_scale);2289 }2290 2291 scale_ptr = N_VGetArrayPointer(solver->kin_f_scale);2292 2293 /* Form scaled Jacobian as needed for automatic scaling and condition number checking*/2294 if (bsop->residual_equation_scaling_mode == jmi_residual_scaling_auto ||2295 bsop->residual_equation_scaling_mode == jmi_residual_scaling_aggressive_auto ||2296 bsop->residual_equation_scaling_mode == jmi_residual_scaling_full_jacobian_auto ||2297 bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid ||2298 bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual)2299 {2300 kin_char_log(solver, 's');2301 for (i = 0; i < N; i++) {2302 int j;2303 /* column scaling is formed by max(abs(nominal), abs(actual_value)) */2304 realtype xscale = RAbs(block->nominal[i]);2305 realtype x = RAbs(block->x[i]);2306 realtype* col_ptr;2307 realtype* scaled_col_ptr;2308 if(x < xscale) x = xscale;2309 if(x < tol) x = tol;2310 col_ptr = DENSE_COL(solver->J, i);2311 scaled_col_ptr = DENSE_COL(solver->J_scale, i);2312 2313 /* row scaling is product of Jac entry and column scaling */2314 for (j = 0; j < N; j++) {2315 realtype dres = col_ptr[j];2316 realtype fscale;2317 fscale = dres * x;2318 scaled_col_ptr[j] = fscale;2319 scale_ptr[j] = MAX(scale_ptr[j], RAbs(fscale));2320 }2321 }2322 }2323 2324 /* put in manual non-zero scales in hybrid & manual cases */2325 if( (bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual)2326 || (bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid)) {2327 for(i = 0; i < N; i++) {2328 if(solver->residual_nominal[i] != 0) {2329 scale_ptr[i] = solver->residual_nominal[i];2330 }2331 }2332 }2333 2334 if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_auto2335 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_aggressive_auto2336 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_full_jacobian_auto2337 || bsop->residual_equation_scaling_mode == jmi_residual_scaling_hybrid) {2338 solver->using_max_min_scaling_flag = 0; /* NOT using max/min scaling */2339 /* check that scaling factors have reasonable magnitude */2340 for(i = 0; i < N; i++) {2341 if(scale_ptr[i] < 1/bsop->max_residual_scaling_factor) {2342 int j, maxInJacIndex = 0;2343 realtype **jac = solver->J_scale->cols;2344 realtype maxInJac = RAbs(jac[0][i]);2345 solver->using_max_min_scaling_flag = 1; /* Using maximum scaling, singular Jacobian? */2346 for(j = 0; j < N; j++) {2347 if(RAbs(maxInJac) < RAbs(jac[j][i])) {2348 maxInJac = jac[j][i];2349 maxInJacIndex = j;2350 }2351 }2352 2353 scale_ptr[i] = bsop->max_residual_scaling_factor;2354 jmi_log_node(block->log, logWarning, "MaxScalingUsed", "Poor scaling in <block: %s>. "2355 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).",2356 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(solver->J, i, maxInJacIndex) ,maxInJac);2357 }2358 else if(scale_ptr[i] > 1/bsop->min_residual_scaling_factor) {2359 int j, maxInJacIndex = 0;2360 realtype **jac = solver->J_scale->cols;2361 realtype maxInJac = RAbs(jac[0][i]);2362 /* Likely not a problem: solver->using_max_min_scaling_flag = 1; -- Using minimum scaling */2363 for(j = 0; j < N; j++) {2364 if(RAbs(maxInJac) < RAbs(jac[j][i])) {2365 maxInJac = jac[j][i];2366 maxInJacIndex = j;2367 }2368 }2369 2370 if (scale_ptr[i] > solver->residual_heuristic_nominal[i]/bsop->min_residual_scaling_factor) {2371 scale_ptr[i] = bsop->min_residual_scaling_factor/solver->residual_heuristic_nominal[i];2372 jmi_log_node(block->log, logWarning, "MinScalingUsed", "Poor scaling in <block: %s>. "2373 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).",2374 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(solver->J, i, maxInJacIndex) ,maxInJac);2375 } else {2376 scale_ptr[i] = 1/scale_ptr[i];2377 jmi_log_node(block->log, logWarning, "MinScalingExceeded", "Poor scaling in <block: %s> but will allow it based on structure of block. "2378 "Consider changes in the model. Partial derivative of <equation: %I> with respect to <Iter: #r%d#> is <dRes_dIter: %g> (<dRes_dIter_scaled: %g>).",2379 block->label, i, block->value_references[maxInJacIndex], DENSE_ELEM(solver->J, i, maxInJacIndex) ,maxInJac);2380 }2381 }2382 else2383 scale_ptr[i] = 1/scale_ptr[i];2384 }2385 2386 if (block->callbacks->log_options.log_level >= 4) {2387 jmi_log_node_t outer = jmi_log_enter_fmt(block->log, logInfo, "ResidualScalingUpdated", "<block:%s>", block->label);2388 if (block->callbacks->log_options.log_level >= 5) {2389 jmi_log_node_t inner = jmi_log_enter_vector_(block->log, outer, logInfo, "scaling");2390 realtype* res = scale_ptr;2391 for (i=0;i<N;i++) jmi_log_real_(block->log, 1/res[i]);2392 jmi_log_leave(block->log, inner);2393 }2394 jmi_log_leave(block->log, outer);2395 }2396 } else if(bsop->residual_equation_scaling_mode == jmi_residual_scaling_manual) {2397 for(i = 0; i < N; i++) {2398 scale_ptr[i] = 1/scale_ptr[i];2399 }2400 /* Scaling is not updated */2401 if (block->callbacks->log_options.log_level >= 4) {2402 jmi_log_node_t outer = jmi_log_enter_fmt(block->log, logInfo, "ResidualScalingUpdated", "<block:%s>", block->label);2403 if (block->callbacks->log_options.log_level >= 5) {2404 jmi_log_node_t inner = jmi_log_enter_vector_(block->log, outer, logInfo, "scaling");2405 realtype* res = scale_ptr;2406 for (i=0;i<N;i++) jmi_log_real_(block->log, 1/res[i]);2407 jmi_log_leave(block->log, inner);2408 }2409 jmi_log_leave(block->log, outer);2410 }2411 }2412 2413 if (solver->using_max_min_scaling_flag && !solver->J_is_singular_flag) {2414 realtype cond = jmi_calculate_jacobian_condition_number(block);2415 2416 jmi_log_node(block->log, logInfo, "Regularization",2417 "Calculated condition number in <block: %s>. Regularizing if <cond: %E> is greater than <regtol: %E>", block->label, cond, solver->kin_reg_tol);2418 if (cond > solver->kin_reg_tol) {2419 if(N > 1 && solver->handling_of_singular_jacobian_flag == JMI_REGULARIZATION) {2420 int info;2421 jmi_kinsol_reg_matrix(block);2422 dgetrf_( &block->n, &block->n, solver->JTJ->data, &block->n, solver->lapack_ipiv, &info);2423 }2424 solver->J_is_singular_flag = 1;2425 }2426 }2427 2428 2429 /* estimate condition number of the scaled jacobian2430 and scale function tolerance with it. */2431 if((N > 1) && bsop->check_jac_cond_flag){2432 realtype* scaled_col_ptr;2433 char norm = 'I';2434 double Jnorm = 1.0, Jcond = 1.0;2435 int info;2436 if(use_scaling_flag) {2437 for(i = 0; i < N; i++){2438 int j;2439 scaled_col_ptr = DENSE_COL(solver->J_scale, i);2440 for(j = 0; j < N; j++){2441 scaled_col_ptr[j] = scaled_col_ptr[j] * scale_ptr[j];2442 }2443 }2444 } else {2445 DenseCopy(solver->J, solver->J_scale);2446 }2447 2448 dgetrf_( &N, &N, solver->J_scale->data, &N, solver->lapack_iwork, &info);2449 if(info > 0) {2450 jmi_log_node(block->log, logWarning, "SingularJacobian",2451 "Singular Jacobian detected when checking condition number in <block:%s>. Solver may fail to converge.", block->label);2452 }2453 else {2454 dgecon_(&norm, &N, solver->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info);2455 2456 if(tol * Jcond < UNIT_ROUNDOFF) {2457 jmi_log_node_t node = jmi_log_enter_fmt(block->log, logWarning, "IllConditionedJacobian",2458 "<JacobianInverseConditionEstimate:%E> Solver may fail to converge in <block: %s>.", Jcond, block->label);2459 if (block->callbacks->log_options.log_level >= 4) {2460 jmi_log_reals(block->log, node, logWarning, "ivs", N_VGetArrayPointer(solver->kin_y), block->n);2461 }2462 jmi_log_leave(block->log, node);2463 2464 }2465 else {2466 jmi_log_node(block->log, logInfo, "JacobianCondition",2467 "<JacobianInverseConditionEstimate:%E>", Jcond);2468 }2469 }2470 }2471 return;2472 2296 } 2473 2297 … … 2493 2317 solver->kin_y = N_VMake_Serial(n, block->x); 2494 2318 solver->kin_y_scale = N_VNew_Serial(n); 2495 solver->kin_f_scale = N_VNew_Serial(n);2496 2319 solver->gradient = N_VNew_Serial(n); 2497 2320 solver->last_residual = N_VNew_Serial(n); 2498 solver->residual_nominal = (realtype*)calloc(n+1,sizeof(realtype));2499 solver->residual_heuristic_nominal = (realtype*)calloc(n+1,sizeof(realtype));2500 solver->kin_scale_update_time = -1.0;2501 2321 solver->kin_jac_update_time = -1.0; 2502 2322 /*NOTE: it'd be nice to use "jmi->newton_tolerance" here … … 2505 2325 solver->kin_ftol = UROUND; /* block->options->min_tol; */ 2506 2326 solver->kin_stol = block->options->min_tol; 2507 solver->using_max_min_scaling_flag = 0; /* Not using max/min scaling */2508 2327 solver->has_compression_setup_flag = FALSE; 2509 2328 solver->is_first_newton_solve_flag = TRUE; 2510 2329 solver->current_nni = 0; 2511 2330 2512 solver->J = NewDenseMat(n ,n);2513 2331 solver->JTJ = NewDenseMat(n ,n); 2514 2332 solver->J_LU = NewDenseMat(n ,n); 2515 solver->J_scale = NewDenseMat(n ,n);2516 2333 solver->J_sing = NewDenseMat(n, n); 2517 2334 solver->J_SVD_U = NewDenseMat(n, n); … … 2549 2366 /* Initialize scaling to 1.0 - defaults */ 2550 2367 N_VConst_Serial(1.0,solver->kin_y_scale); 2551 2552 /* Initial equation scaling is 1.0 */2553 N_VConst_Serial(1.0,solver->kin_f_scale);2554 2368 2555 2369 flag = KINInit(solver->kin_mem, kin_f, solver->kin_y); /*Initialize Kinsol*/ … … 2637 2451 N_VDestroy_Serial(solver->kin_y); 2638 2452 N_VDestroy_Serial(solver->kin_y_scale); 2639 N_VDestroy_Serial(solver->kin_f_scale);2640 2453 N_VDestroy_Serial(solver->gradient); 2641 2454 N_VDestroy_Serial(solver->last_residual); 2642 free(solver->residual_nominal);2643 free(solver->residual_heuristic_nominal);2644 DestroyMat(solver->J);2645 2455 DestroyMat(solver->JTJ); 2646 2456 DestroyMat(solver->J_LU); 2647 DestroyMat(solver->J_scale);2648 2457 DestroyMat(solver->J_sing); 2649 2458 DestroyMat(solver->J_SVD_U); … … 2771 2580 } 2772 2581 jmi_kinsol_solver_print_solve_start(block, &topnode); 2773 flag = KINSol(solver->kin_mem, solver->kin_y, strategy, solver->kin_y_scale, solver->kin_f_scale);2582 flag = KINSol(solver->kin_mem, solver->kin_y, strategy, solver->kin_y_scale, block->f_scale); 2774 2583 if(flag == KIN_INITIAL_GUESS_OK) { /* last_fnorm not up to date in this case */ 2775 2584 double max_residual = 0.0; … … 2777 2586 realtype* f; 2778 2587 char msg[256]; 2779 realtype* residual_scaling_factors = NV_DATA_S( solver->kin_f_scale);2588 realtype* residual_scaling_factors = NV_DATA_S(block->f_scale); 2780 2589 2781 2590 /*kin_f(solver->kin_y, solver->work_vector, block); */ … … 2794 2603 solver->last_max_residual= max_residual; 2795 2604 solver->last_max_residual_index = max_index; 2796 solver->last_fnorm = N_VWL2Norm(kin_mem->kin_fval, solver->kin_f_scale);2605 solver->last_fnorm = N_VWL2Norm(kin_mem->kin_fval, block->f_scale); 2797 2606 kin_mem->kin_fnorm = solver->last_fnorm; 2798 2607 sprintf(msg, "nni = %4ld nfe = %6ld fnorm = %26.16g", kin_mem->kin_nni, kin_mem->kin_nfe, solver->last_fnorm); … … 2810 2619 } else if (flag == KIN_LINESEARCH_NONCONV || flag == KIN_STEP_LT_STPTOL) { 2811 2620 realtype fnorm; 2812 N_VProd( solver->kin_f_scale, kin_mem->kin_fval, solver->work_vector);2621 N_VProd(block->f_scale, kin_mem->kin_fval, solver->work_vector); 2813 2622 fnorm =N_VMaxNorm(solver->work_vector); 2814 2623 if((fnorm <= solver->kin_stol && !block->options->solver_exit_criterion_mode == jmi_exit_criterion_step_residual) … … 2826 2635 if(block->options->check_jac_cond_flag) { 2827 2636 int i, info, N = block->n; 2828 realtype* scale_ptr = N_VGetArrayPointer( solver->kin_f_scale);2637 realtype* scale_ptr = N_VGetArrayPointer(block->f_scale); 2829 2638 realtype tol = solver->kin_stol; 2830 2639 if(block->options->residual_equation_scaling_mode !=0) { 2831 2640 for(i = 0; i < N; i++){ 2832 2641 int j; 2833 realtype* scaled_col_ptr = DENSE_COL( solver->J_scale, i);2834 realtype* col_ptr = DENSE_COL( solver->J, i);2642 realtype* scaled_col_ptr = DENSE_COL(block->J_scale, i); 2643 realtype* col_ptr = DENSE_COL(block->J, i); 2835 2644 realtype xscale = RAbs(block->nominal[i]); 2836 2645 realtype x = RAbs(block->x[i]); … … 2842 2651 } 2843 2652 } else { 2844 DenseCopy( solver->J, solver->J_scale);2845 } 2846 2847 dgetrf_( &N, &N, solver->J_scale->data, &N, solver->lapack_iwork, &info);2653 DenseCopy(block->J, block->J_scale); 2654 } 2655 2656 dgetrf_( &N, &N, block->J_scale->data, &N, solver->lapack_iwork, &info); 2848 2657 if(info > 0) { 2849 2658 jmi_log_node(block->log, logWarning, "SingularJacobian", … … 2853 2662 char norm = 'I'; 2854 2663 double Jnorm = 1.0, Jcond = 1.0; 2855 dgecon_(&norm, &N, solver->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info);2664 dgecon_(&norm, &N, block->J_scale->data, &N, &Jnorm, &Jcond, solver->lapack_work, solver->lapack_iwork,&info); 2856 2665 2857 2666 if(tol * Jcond < UNIT_ROUNDOFF) { … … 2893 2702 2894 2703 if(block->init) { 2895 jmi_setup_f_residual_scaling(block);2896 2704 flag = jmi_kinsol_init(block); 2897 2705 if(flag) return flag; … … 2925 2733 2926 2734 /* update the scaling only once per time step */ 2927 if(block->init || (block->options->rescale_each_step_flag && (curtime > solver->kin_scale_update_time)) || block->force_rescaling) {2735 if(block->init || (block->options->rescale_each_step_flag && (curtime > block->scale_update_time)) || block->force_rescaling) { 2928 2736 jmi_update_f_scale(block); 2737 jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(block); 2929 2738 } 2930 2739 … … 2971 2780 solver->use_steepest_descent_flag = 1; 2972 2781 2973 flag = KINSol(solver->kin_mem, solver->kin_y, KIN_LINESEARCH, solver->kin_y_scale, solver->kin_f_scale);2782 flag = KINSol(solver->kin_mem, solver->kin_y, KIN_LINESEARCH, solver->kin_y_scale, block->f_scale); 2974 2783 if(flag == KIN_INITIAL_GUESS_OK) { 2975 2784 flag = KIN_SUCCESS; … … 2998 2807 /* Update the scaling */ 2999 2808 jmi_update_f_scale(block); 2809 jmi_regularize_and_do_condition_estimate_on_scaled_jacobian(block); 3000 2810 3001 2811 /* For the second solve set tight tolerance on the step and specified tolerance on the residual */ … … 3121 2931 DenseCopy(solver->saved_state->J_modified, solver->J_LU); 3122 2932 } 3123 DenseCopy(solver->saved_state->J, solver->J);3124 3125 solver->kin_scale_update_time = solver->saved_state->kin_scale_update_time;2933 DenseCopy(solver->saved_state->J, block->J); 2934 2935 block->scale_update_time = solver->saved_state->kin_scale_update_time; 3126 2936 block->force_rescaling = solver->saved_state->force_rescaling; 3127 2937 … … 3130 2940 solver->J_is_singular_flag = solver->saved_state->J_is_singular_flag; 3131 2941 ((struct KINMemRec *)solver->kin_mem)->kin_nnilset = ((struct KINMemRec *)solver->kin_mem)->kin_nni - solver->saved_state->mbset; 3132 memcpy(N_VGetArrayPointer( solver->kin_f_scale), N_VGetArrayPointer(solver->saved_state->kin_f_scale), block->n*sizeof(realtype));2942 memcpy(N_VGetArrayPointer(block->f_scale), N_VGetArrayPointer(solver->saved_state->kin_f_scale), block->n*sizeof(realtype)); 3133 2943 memcpy(N_VGetArrayPointer(solver->kin_y_scale), N_VGetArrayPointer(solver->saved_state->kin_y_scale), block->n*sizeof(realtype)); 3134 2944 memcpy(solver->lapack_ipiv, solver->saved_state->lapack_ipiv, (block->n+2)*sizeof(int)); … … 3139 2949 jmi_log_ints(block->log, node, logInfo, "is_singular", &(block->force_rescaling), 1); 3140 2950 jmi_log_ints(block->log, node, logInfo, "force_rescaling", &(solver->J_is_singular_flag), 1); 3141 jmi_log_reals(block->log, node, logInfo, "residual_scaling_update_time", &( solver->kin_scale_update_time), 1);2951 jmi_log_reals(block->log, node, logInfo, "residual_scaling_update_time", &(block->scale_update_time), 1); 3142 2952 jmi_log_reals(block->log, node, logInfo, "iv_scaling", N_VGetArrayPointer(solver->kin_y_scale), block->n); 3143 jmi_log_reals(block->log, node, logInfo, "residual_scaling", N_VGetArrayPointer( solver->kin_f_scale), block->n);2953 jmi_log_reals(block->log, node, logInfo, "residual_scaling", N_VGetArrayPointer(block->f_scale), block->n); 3144 2954 jmi_log_leave(block->log, node); 3145 2955 } … … 3180 2990 DenseCopy(solver->J_LU, solver->saved_state->J_modified); 3181 2991 } 3182 DenseCopy( solver->J, solver->saved_state->J);2992 DenseCopy(block->J, solver->saved_state->J); 3183 2993 3184 solver->saved_state->kin_scale_update_time = solver->kin_scale_update_time;2994 solver->saved_state->kin_scale_update_time = block->scale_update_time; 3185 2995 solver->saved_state->force_rescaling = block->force_rescaling; 3186 2996 solver->saved_state->force_new_J_flag = solver->force_new_J_flag; … … 3189 2999 solver->saved_state->J_is_singular_flag = solver->J_is_singular_flag; 3190 3000 solver->saved_state->mbset = ((struct KINMemRec *)solver->kin_mem)->kin_nni - ((struct KINMemRec *)solver->kin_mem)->kin_nnilset; 3191 memcpy(N_VGetArrayPointer(solver->saved_state->kin_f_scale),N_VGetArrayPointer( solver->kin_f_scale), block->n*sizeof(realtype));3001 memcpy(N_VGetArrayPointer(solver->saved_state->kin_f_scale),N_VGetArrayPointer(block->f_scale), block->n*sizeof(realtype)); 3192 3002 memcpy(N_VGetArrayPointer(solver->saved_state->kin_y_scale),N_VGetArrayPointer(solver->kin_y_scale), block->n*sizeof(realtype)); 3193 3003 memcpy(solver->saved_state->lapack_ipiv, solver->lapack_ipiv, (block->n+2)*sizeof(int)); … … 3198 3008 jmi_log_ints(block->log, node, logInfo, "is_singular", &(solver->J_is_singular_flag), 1); 3199 3009 jmi_log_ints(block->log, node, logInfo, "force_rescaling", &(solver->J_is_singular_flag), 1); 3200 jmi_log_reals(block->log, node, logInfo, "residual_scaling_update_time", &( solver->kin_scale_update_time), 1);3010 jmi_log_reals(block->log, node, logInfo, "residual_scaling_update_time", &(block->scale_update_time), 1); 3201 3011 jmi_log_reals(block->log, node, logInfo, "iv_scaling", N_VGetArrayPointer(solver->kin_y_scale), block->n); 3202 jmi_log_reals(block->log, node, logInfo, "residual_scaling", N_VGetArrayPointer( solver->kin_f_scale), block->n);3012 jmi_log_reals(block->log, node, logInfo, "residual_scaling", N_VGetArrayPointer(block->f_scale), block->n); 3203 3013 jmi_log_leave(block->log, node); 3204 3014 } … … 3206 3016 return 0; 3207 3017 } 3208 -
trunk/RuntimeLibrary/src/jmi/jmi_kinsol_solver.h
r8384 r8512 58 58 int jmi_kinsol_restore_state(jmi_block_solver_t* block); 59 59 60 /**< \brief Retrieve residual scales used in Kinsol solver */61 double* jmi_kinsol_solver_get_f_scales(jmi_kinsol_solver_t* solver);62 63 60 /**< \brief Convert Kinsol return flag to readable name */ 64 61 const char *jmi_kinsol_flag_to_name(int flag); … … 87 84 88 85 N_Vector kin_y_scale; /**< \brief Work vector for Kinsol scaling of y */ 89 N_Vector kin_f_scale; /**< \brief Work vector for Kinsol scaling of f */90 86 N_Vector gradient; /**< \brief Steepest descent direction */ 91 realtype* residual_nominal; /**< \brief Vector for reading in manual scaling factors for f */92 realtype* residual_heuristic_nominal; /**< \brief Vector for reading in heuristic scaling factors for f */93 realtype kin_scale_update_time; /**< \brief The last time when Kinsol scale was updated */94 87 realtype kin_jac_update_time; /**< \brief The last time when Jacobian was updated */ 95 88 realtype kin_ftol; /**< \brief Tolerance for F */ … … 97 90 realtype kin_reg_tol; /**< \brief Regularization tolerance */ 98 91 99 DlsMat J; /**< \brief The Jacobian matrix */100 92 DlsMat JTJ; /**< \brief The Transpose(J).J used if J is singular */ 101 93 int J_is_singular_flag; /**< \brief A flag indicating that J is singular. Regularized JTJ is setup */ 102 94 int use_steepest_descent_flag; /**< \brief A flag indicating that steepest descent and not Newton direction should be used */ 103 95 int force_new_J_flag; /**< \brief A flag indicating that J needs to be recalculated */ 104 int using_max_min_scaling_flag; /**< \brief A flag indicating if either the maximum scaling is used of the minimum */105 96 int updated_jacobian_flag; /**< \brief A flag indicating if an updated Jacobian is used to solve the system */ 106 97 int handling_of_singular_jacobian_flag; /**< \brief A flag for determining how singular systems should be treated */ 107 98 DlsMat J_LU; /**< \brief Jacobian matrix/it's LU decomposition */ 108 DlsMat J_scale; /**< \brief Jacobian matrix scaled with xnorm for used for fnorm calculation */109 99 DlsMat J_sing; /**< \brief Jacobian matrix/it's right singular vectors */ 110 100 DlsMat J_SVD_U; /**< \brief The left singular vectors */ -
trunk/RuntimeLibrary/src/jmi/jmi_linear_solver.c
r8052 r8512 40 40 /* Initialize work vectors.*/ 41 41 solver->factorization = (jmi_real_t*)calloc(n_x*n_x,sizeof(jmi_real_t)); 42 solver->jacobian = (jmi_real_t*)calloc(n_x*n_x,sizeof(jmi_real_t));43 42 solver->dependent_set = (jmi_real_t*)calloc(n_x*n_x,sizeof(jmi_real_t)); 44 43 solver->jacobian_temp = (jmi_real_t*)calloc(2*n_x*n_x,sizeof(jmi_real_t)); … … 82 81 for (i = 0; i < n_x; i++) { solver->dependent_set[(n_x-1)*n_x+i] = 0; } 83 82 84 memcpy(solver->jacobian_temp, solver->jacobian, n_x*n_x*sizeof(jmi_real_t));83 memcpy(solver->jacobian_temp, block->J->data, n_x*n_x*sizeof(jmi_real_t)); 85 84 /* Compute the null space of A */ 86 85 /* … … 197 196 if (solver->n_extra_rows > 0) { 198 197 for (j = 0; j < n_x; j++) { 199 memcpy(&solver->jacobian_temp[j*(n_x+solver->n_extra_rows)], & solver->jacobian[j*n_x], n_x*sizeof(jmi_real_t));198 memcpy(&solver->jacobian_temp[j*(n_x+solver->n_extra_rows)], &block->J->data[j*n_x], n_x*sizeof(jmi_real_t)); 200 199 memcpy(&solver->jacobian_temp[j*(n_x+solver->n_extra_rows)+n_x], &solver->jacobian_extension[j*n_x], solver->n_extra_rows*sizeof(jmi_real_t)); 201 200 } … … 246 245 A regularization strategy for simple cases singular jac should be introduced. 247 246 */ 248 info = block->F(block->problem_data,NULL, solver->jacobian,JMI_BLOCK_EVALUATE_JACOBIAN);249 memcpy(solver->factorization, solver->jacobian, n_x*n_x*sizeof(jmi_real_t));247 info = block->F(block->problem_data,NULL,block->J->data,JMI_BLOCK_EVALUATE_JACOBIAN); 248 memcpy(solver->factorization, block->J->data, n_x*n_x*sizeof(jmi_real_t)); 250 249 if(info) { 251 250 if(block->init) { … … 275 274 for (j = 0; j < n_x; j++) { 276 275 /* Unrecoverable error*/ 277 if ( solver->jacobian[i*n_x+j] - solver->jacobian[i*n_x+j] != 0) {276 if ( block->J->data[i*n_x+j] - block->J->data[i*n_x+j] != 0) { 278 277 jmi_log_node(block->log, logError, "NaNOutput", "Not a number in the Jacobian <row: %I> <col: %I> from <block: %s>", 279 278 i,j, block->label); … … 289 288 "Linear solver invoked for <block:%s>", block->label); 290 289 jmi_log_reals(block->log, destnode, logInfo, "ivs", block->x, block->n); 291 jmi_log_real_matrix(block->log, destnode, logInfo, "A", solver->jacobian, block->n, block->n);290 jmi_log_real_matrix(block->log, destnode, logInfo, "A", block->J->data, block->n, block->n); 292 291 } 293 292 … … 386 385 dgelss_(&n_rows, &n_x, &i, solver->jacobian_temp, &n_rows, solver->rhs, &n_rows ,solver->singular_values, &rcond, &rank, solver->rwork, &iwork, &info); 387 386 } else { 388 memcpy(solver->jacobian_temp, solver->jacobian, n_x*n_x*sizeof(jmi_real_t));387 memcpy(solver->jacobian_temp, block->J->data, n_x*n_x*sizeof(jmi_real_t)); 389 388 dgelss_(&n_x, &n_x, &i, solver->jacobian_temp, &n_x, solver->rhs, &n_x ,solver->singular_values, &rcond, &rank, solver->rwork, &iwork, &info); 390 389 } … … 395 394 } 396 395 397 if(block->callbacks->log_options.log_level >= 5){398 jmi_log_node(block->log, logInfo, "Info", "Successfully calculated the minimum norm solution to the linear system in <block: %s>", block->label);399 }400 396 }else{ 401 397 /* … … 449 445 block->F(block->problem_data,block->x, solver->rhs, JMI_BLOCK_EVALUATE); 450 446 447 /* Check if the calculated solution from minimum norm is a valid solution to the original problem */ 448 if(solver->singular_jacobian==1) { 449 double scaledMaxNorm; 450 jmi_update_f_scale(block); 451 scaledMaxNorm = calculate_scaled_residual_norm(solver->rhs, N_VGetArrayPointer(block->f_scale), block->n); 452 if(scaledMaxNorm <= block->options->res_tol) { 453 if(block->callbacks->log_options.log_level >= 5){ 454 jmi_log_node(block->log, logInfo, "Info", "Successfully calculated the minimum norm solution to the linear system in <block: %s>", block->label); 455 } 456 } else { 457 info = -1; 458 destnode = jmi_log_enter_fmt(block->log, logError, "UnsolveableLinearSystem", "Failed to calculate a valid minimum norm solution to the linear system in <block: %s> at <t: %f>", block->label, block->cur_time); 459 jmi_log_reals(block->log, destnode, logError, "residual", solver->rhs, block->n); 460 jmi_log_reals(block->log, destnode, logError, "scaled_max_norm", &(scaledMaxNorm), 1); 461 jmi_log_leave(block->log, destnode); 462 } 463 464 } 465 451 466 return info==0? 0: -1; 452 467 } … … 456 471 free(solver->ipiv); 457 472 free(solver->factorization); 458 free(solver->jacobian);459 473 free(solver->singular_values); 460 474 free(solver->singular_vectors); -
trunk/RuntimeLibrary/src/jmi/jmi_linear_solver.h
r7216 r8512 58 58 int* ipiv; /**< \brief Work vector needed for dgesv */ 59 59 jmi_real_t* factorization; /**< \brief Matrix for storing the Jacobian factorization */ 60 jmi_real_t* jacobian; /**< \brief Matrix for storing the Jacobian */61 60 jmi_real_t* jacobian_temp; /**< \brief Matrix for storing the Jacobian */ 62 61 jmi_real_t* singular_values; /**< \brief Vector for the singular values of the Jacobian */
Note: See TracChangeset
for help on using the changeset viewer.