xref: /petsc/share/petsc/saws/js/listLogic.js (revision 162a98829fa806f10ebc3598a04994291653982c)
1/*
2  This function is called when a pc_type option is changed (new options may need to be displayed and/or old ones removed
3*/
4
5$(document).on("change","select[id^='pc_type']",function() {
6
7    //get the pc option
8    var pcValue   = $(this).val();
9    var id        = $(this).attr("id"); //really should not be used in this method. there are better ways of getting information
10    var endtag    = id.substring(id.indexOf("0"),id.length);
11    var parentDiv = "solver" + endtag;
12
13    removeAllChildren(endtag); //this function also changes matInfo as needed
14
15    //record pc_type in matInfo
16    matInfo[endtag].pc_type = pcValue;
17
18    if (pcValue == "mg") {
19        var defaults = getDefaults("mg",matInfo[endtag].symm, matInfo[endtag].posdef, matInfo[endtag].logstruc);
20        var defaultMgLevels = defaults.pc_mg_levels;
21
22        matInfo[endtag].pc_mg_levels = defaultMgLevels;
23        matInfo[endtag].pc_mg_type   = defaults.pc_mg_type;
24
25        //first add options related to multigrid (pc_mg_type and pc_mg_levels)
26        $("#" + parentDiv).append("<br><b>MG Type &nbsp;&nbsp;</b><select id=\"pc_mg_type" + endtag + "\"></select>");
27        $("#" + parentDiv).append("<br><b>MG Levels </b><input type='text' id=\'pc_mg_levels" + endtag + "\' maxlength='4'>");
28
29        populateList("mg",endtag);
30
31        $("#pc_mg_levels" + endtag).val(defaultMgLevels);
32        $("#pc_mg_type" + endtag).val(defaults.pc_mg_type);
33
34        //display options for each level
35        for(var i=defaultMgLevels-1; i>=0; i--) {
36            var childEndtag = endtag + "_" + i;
37
38            matInfo[childEndtag] = {
39                pc_type : defaults.sub_pc_type,
40                ksp_type: defaults.sub_ksp_type,
41                symm: matInfo[endtag].symm, //inherit !!
42                posdef: matInfo[endtag].posdef,
43                logstruc: matInfo[endtag].logstruc
44            };
45
46            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
47
48            $("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
49            if(i == 0) //coarse grid solver (level 0)
50                $("#solver" + childEndtag).append("<br><b>Coarse Grid Solver (Level 0)  </b>");
51            else
52                $("#solver" + childEndtag).append("<br><b>Smoothing (Level " + i + ")  </b>");
53
54            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
55	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
56
57            populateList("ksp",childEndtag);
58            populateList("pc",childEndtag);
59
60	    //set defaults
61            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
62	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
63            //trigger both to add additional options
64            $("#ksp_type" + childEndtag).trigger("change");
65            $("#pc_type" + childEndtag).trigger("change");
66        }
67
68    }
69
70    else if(pcValue == "gamg") {
71        var defaults = getDefaults("gamg",matInfo[endtag].symm, matInfo[endtag].posdef, matInfo[endtag].logstruc);
72        var defaultGamgLevels = defaults.pc_gamg_levels;
73
74        matInfo[endtag].pc_gamg_levels = defaultGamgLevels;
75        matInfo[endtag].pc_gamg_type   = defaults.pc_gamg_type;
76
77        //first add options related to multigrid (pc_gamg_type and pc_gamg_levels)
78        $("#" + parentDiv).append("<br><b>GAMG Type &nbsp;&nbsp;</b><select id=\"pc_gamg_type" + endtag + "\"></select>");
79        $("#" + parentDiv).append("<br><b>GAMG Levels </b><input type='text' id=\'pc_gamg_levels" + endtag + "\' maxlength='4'>");
80
81        populateList("gamg",endtag);
82
83        $("#pc_gamg_levels" + endtag).val(defaultGamgLevels);
84        $("#pc_gamg_type" + endtag).val(defaults.pc_gamg_type);
85
86        //display options for each level
87        for(var i=defaultGamgLevels-1; i>=0; i--) {
88            var childEndtag = endtag + "_" + i;
89
90            matInfo[childEndtag] = {
91                pc_type : defaults.sub_pc_type,
92                ksp_type: defaults.sub_ksp_type,
93                symm: matInfo[endtag].symm, //inherit !!
94                posdef: matInfo[endtag].posdef,
95                logstruc: matInfo[endtag].logstruc
96            };
97
98            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
99
100            $("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
101            if(i == 0) //coarse grid solver (level 0)
102                $("#solver" + childEndtag).append("<br><b>Coarse Grid Solver (Level 0)  </b>");
103            else
104                $("#solver" + childEndtag).append("<br><b>Smoothing (Level " + i + ")  </b>");
105
106            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
107	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
108
109            populateList("ksp",childEndtag);
110            populateList("pc",childEndtag);
111
112	    //set defaults
113            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
114	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
115            //trigger both to add additional options
116            $("#ksp_type" + childEndtag).trigger("change");
117            $("#pc_type" + childEndtag).trigger("change");
118        }
119
120    }
121
122    else if (pcValue == "redundant") {
123        var defaults = getDefaults("redundant",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
124        var defaultRedundantNumber = defaults.pc_redundant_number;
125        var childEndtag = endtag + "_0";
126
127        matInfo[endtag].pc_redundant_number = defaultRedundantNumber;
128
129        //first add options related to redundant (pc_redundant_number)
130        $("#" + parentDiv).append("<br><b>Redundant Number </b><input type='text' id=\'pc_redundant_number" + endtag + "\' maxlength='4'>");
131        $("#pc_redundant_number" + endtag).val(defaultRedundantNumber);
132
133        matInfo[childEndtag] = {
134            pc_type : defaults.sub_pc_type,
135            ksp_type: defaults.sub_ksp_type,
136            symm: matInfo[endtag].symm, //inherit!!
137            posdef: matInfo[endtag].posdef,
138            logstruc: matInfo[endtag].logstruc
139        };
140
141        var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
142	$("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
143	$("#solver" + childEndtag).append("<br><b>Redundant Solver Options </b>");
144	$("#solver" + childEndtag).append("<br><b>KSP    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag + "\"></select>");
145	$("#solver" + childEndtag).append("<br><b>PC     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
146
147	populateList("ksp",childEndtag);
148        populateList("pc",childEndtag);
149
150        //set defaults
151        $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
152	$("#pc_type" + childEndtag).val(defaults.sub_pc_type);
153        //trigger both to add additional options
154        $("#ksp_type" + childEndtag).trigger("change");
155        $("#pc_type" + childEndtag).trigger("change");
156    }
157
158    else if (pcValue == "bjacobi") {
159        var defaults = getDefaults("bjacobi",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
160        var defaultBjacobiBlocks = defaults.pc_bjacobi_blocks;
161        var childEndtag = endtag + "_0";
162
163        matInfo[endtag].pc_bjacobi_blocks   = defaultBjacobiBlocks;
164
165        //first add options related to bjacobi (pc_bjacobi_blocks)
166        $("#" + parentDiv).append("<br><b>Bjacobi Blocks </b><input type='text' id=\'pc_bjacobi_blocks" + endtag + "\' maxlength='4'>");
167        $("#pc_bjacobi_blocks" + endtag).val(defaultBjacobiBlocks);
168
169        matInfo[childEndtag] = {
170            pc_type : defaults.sub_pc_type,
171            ksp_type: defaults.sub_ksp_type,
172            symm: matInfo[endtag].symm, //inherit!!
173            posdef: matInfo[endtag].posdef,
174            logstruc: matInfo[endtag].logstruc
175        };
176
177        var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
178
179	$("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
180
181	$("#solver" + childEndtag).append("<br><b>Bjacobi Solver Options </b>");
182	$("#solver" + childEndtag).append("<br><b>KSP    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag + "\"></select>");
183	$("#solver" + childEndtag).append("<br><b>PC     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
184
185	populateList("ksp",childEndtag);
186        populateList("pc",childEndtag);
187
188        //set defaults
189        $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
190	$("#pc_type" + childEndtag).val(defaults.sub_pc_type);
191        //trigger both to add additional options
192        $("#ksp_type" + childEndtag).trigger("change");
193        $("#pc_type" + childEndtag).trigger("change");
194    }
195
196    else if (pcValue == "asm") {
197        var defaults = getDefaults("asm",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
198
199        var defaultAsmBlocks  = defaults.pc_asm_blocks;
200        var defaultAsmOverlap = defaults.pc_asm_overlap;
201        var childEndtag = endtag + "_0";
202
203        matInfo[endtag].pc_asm_blocks  = defaultAsmBlocks;
204        matInfo[endtag].pc_asm_overlap = defaultAsmOverlap;
205
206        //first add options related to ASM
207        $("#" + parentDiv).append("<br><b>ASM blocks   &nbsp;&nbsp;</b><input type='text' id=\"pc_asm_blocks" + endtag + "\" maxlength='4'>");
208	$("#" + parentDiv).append("<br><b>ASM overlap   </b><input type='text' id=\"pc_asm_overlap" + endtag + "\" maxlength='4'>");
209        $("#pc_asm_blocks" + endtag).val(defaultAsmBlocks);
210        $("#pc_asm_overlap" + endtag).val(defaultAsmOverlap);
211
212        matInfo[childEndtag] = {
213            pc_type : defaults.sub_pc_type,
214            ksp_type: defaults.sub_ksp_type,
215            symm: matInfo[endtag].symm, //inherit!!
216            posdef: matInfo[endtag].posdef,
217            logstruc: matInfo[endtag].logstruc
218        };
219
220        var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
221
222	$("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
223
224	$("#solver" + childEndtag).append("<br><b>ASM Solver Options </b>");
225	$("#solver" + childEndtag).append("<br><b>KSP    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag + "\"></select>");
226	$("#solver" + childEndtag).append("<br><b>PC     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
227
228	populateList("ksp",childEndtag);
229        populateList("pc",childEndtag);
230
231        //set defaults
232        $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
233	$("#pc_type" + childEndtag).val(defaults.sub_pc_type);
234        //trigger both to add additional options
235        $("#ksp_type" + childEndtag).trigger("change");
236        $("#pc_type" + childEndtag).trigger("change");
237    }
238
239    else if (pcValue == "ksp") {
240        var defaults = getDefaults("ksp",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
241        var childEndtag = endtag + "_0";
242
243        matInfo[childEndtag] = {
244            pc_type : defaults.sub_pc_type,
245            ksp_type: defaults.sub_ksp_type,
246            symm: matInfo[endtag].symm, //inherit!!
247            posdef: matInfo[endtag].posdef,
248            logstruc: matInfo[endtag].logstruc
249        };
250
251        var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
252
253	$("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
254
255	$("#solver" + childEndtag).append("<br><b>KSP Solver Options </b>");
256	$("#solver" + childEndtag).append("<br><b>KSP    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag + "\"></select>");
257	$("#solver" + childEndtag).append("<br><b>PC     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
258
259	populateList("ksp",childEndtag);
260        populateList("pc",childEndtag);
261
262        //set defaults
263        $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
264	$("#pc_type" + childEndtag).val(defaults.sub_pc_type);
265        //trigger both to add additional options
266        $("#ksp_type" + childEndtag).trigger("change");
267        $("#pc_type" + childEndtag).trigger("change");
268    }
269
270    else if (pcValue == "fieldsplit") {
271        /*if(!matInfo[endtag].logstruc) {//do nothing if not logstruc
272            alert("Error: Fieldsplit can only be used on logically block-structured matrix!");
273            return;
274        }*/
275        var defaults = getDefaults("fieldsplit",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
276        var defaultFieldsplitBlocks = defaults.pc_fieldsplit_blocks;
277
278        matInfo[endtag].pc_fieldsplit_type   = defaults.pc_fieldsplit_type;
279        matInfo[endtag].pc_fieldsplit_blocks = defaults.pc_fieldsplit_blocks;
280
281        //first add options related to fieldsplit (pc_fieldsplit_type and pc_fieldsplit_blocks)
282        $("#" + parentDiv).append("<br><b>Fieldsplit Type &nbsp;&nbsp;</b><select id=\"pc_fieldsplit_type" + endtag + "\"></select>");
283        $("#" + parentDiv).append("<br><b>Fieldsplit Blocks </b><input type='text' id=\"pc_fieldsplit_blocks" + endtag + "\" maxlength='4'>");
284
285        populateList("fieldsplit",endtag);
286
287        $("#pc_fieldsplit_blocks" + endtag).val(defaultFieldsplitBlocks);
288        $("#pc_fieldsplit_type" + endtag).val(defaults.pc_fieldsplit_type);
289
290        for(var i=defaultFieldsplitBlocks-1; i>=0; i--) {
291            var childEndtag = endtag + "_" + i;
292
293            matInfo[childEndtag] = {
294                pc_type : defaults.sub_pc_type,
295                ksp_type: defaults.sub_ksp_type,
296                symm: matInfo[endtag].symm, //inherit!!
297                posdef: matInfo[endtag].posdef,
298                logstruc: false //this one is false to prevent infinite recursion
299            };
300
301            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
302
303            $("#" + parentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
304            $("#solver" + childEndtag).append("<br><b>Fieldsplit " + i + " Options (Matrix is <input type=\"checkbox\" id=\"symm" + childEndtag + "\">symmetric,  <input type=\"checkbox\" id=\"posdef" + childEndtag + "\">positive definite, <input type=\"checkbox\" id=\"logstruc" + childEndtag + "\">block structured)</b>");
305
306            //special for fieldsplit
307            if(matInfo[childEndtag].symm)
308                $("#symm" + childEndtag).attr("checked",true);
309            if(matInfo[childEndtag].posdef)
310                $("#posdef" + childEndtag).attr("checked",true);
311            if(matInfo[childEndtag].logstruc)
312                $("#logstruc" + childEndtag).attr("checked",true);
313
314            if(matInfo[endtag].symm)
315                $("#symm" + childEndtag).attr("disabled",true);
316            if(matInfo[endtag].posdef)
317                $("#posdef" + childEndtag).attr("disabled",true);
318            if(!matInfo[endtag].symm)
319                $("#posdef" + childEndtag).attr("disabled",true);
320
321            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
322	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
323
324            populateList("ksp",childEndtag);
325            populateList("pc",childEndtag);
326
327	    //set defaults
328            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
329	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
330            //trigger both to add additional options
331            $("#ksp_type" + childEndtag).trigger("change");
332            $("#pc_type" + childEndtag).trigger("change");
333        }
334    }
335    refresh(); //refresh diagrams after any change in pc
336});
337
338//called when a ksp option is changed
339//simply adjust ksp_type in matInfo
340$(document).on("change","select[id^='ksp_type']",function() {
341
342    var kspValue   = $(this).val();
343    var id         = $(this).attr("id");//really should not be used in this method. there are better ways of getting information
344    var endtag     = id.substring(id.indexOf("0"),id.length);
345
346    matInfo[endtag].ksp_type = kspValue;
347    refresh(); //refresh diagrams after any change in ksp
348});
349
350//need to add a bunch of methods here for changing each variable: pc_fieldsplit_blocks, pc_asm_blocks, pc_redundant_number, etc
351//these methods seem incredibly redundant. perhaps there is a better way to write these.
352$(document).on("change","select[id^='pc_mg_type']",function() {
353
354    var mgType     = $(this).val();
355    var id         = $(this).attr("id"); //really should not be used in this method. there are better ways of getting information
356    var endtag     = id.substring(id.indexOf("0"),id.length);
357
358    matInfo[endtag].pc_mg_type = mgType;
359    refresh();
360});
361
362$(document).on("change","select[id^='pc_gamg_type']",function() {
363
364    var gamgType   = $(this).val();
365    var id         = $(this).attr("id"); //really should not be used in this method. there are better ways of getting information
366    var endtag     = id.substring(id.indexOf("0"),id.length);
367
368    matInfo[endtag].pc_gamg_type = gamgType;
369    refresh();
370});
371
372$(document).on("change","select[id^='pc_fieldsplit_type']",function() {
373
374    var fieldsplitType  = $(this).val();
375    var id              = $(this).attr("id"); //really should not be used in this method. there are better ways of getting information
376    var endtag          = id.substring(id.indexOf("0"),id.length);
377
378    matInfo[endtag].pc_fieldsplit_type = fieldsplitType;
379    refresh();
380});
381
382$(document).on("keyup","input[id^='pc_asm_blocks']",function() {
383
384    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
385        return;
386
387    var id     = this.id;
388    var endtag = id.substring(id.indexOf(0),id.length);
389    var val    = $(this).val();
390
391    matInfo[endtag].pc_asm_blocks = val;
392    refresh(); //refresh diagrams
393});
394
395$(document).on("keyup","input[id^='pc_asm_overlap']",function() {
396
397    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
398        return;
399
400    var id     = this.id;
401    var endtag = id.substring(id.indexOf(0),id.length);
402    var val    = $(this).val();
403
404    matInfo[endtag].pc_asm_overlap = val;
405    refresh();
406});
407
408$(document).on("keyup","input[id^='pc_bjacobi_blocks']",function() {
409
410    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
411        return;
412
413    var id     = this.id;
414    var endtag = id.substring(id.indexOf(0),id.length);
415    var val    = $(this).val();
416
417    matInfo[endtag].pc_bjacobi_blocks = val;
418    refresh(); //refresh diagrams
419});
420
421$(document).on("keyup","input[id^='pc_redundant_number']",function() {
422
423    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
424        return;
425
426    var id     = this.id;
427    var endtag = id.substring(id.indexOf(0),id.length);
428    var val    = $(this).val();
429
430    matInfo[endtag].pc_redundant_number = val;
431    refresh();
432});
433
434
435//input: endtag of the parent
436function removeAllChildren(endtag) {
437
438    var numChildren = getNumChildren(matInfo, endtag);
439
440    for(var i=0; i<numChildren; i++) {
441        var childEndtag = endtag + "_" + i;
442
443        if(getNumChildren(matInfo, childEndtag) > 0)//this child has more children
444        {
445            removeAllChildren(childEndtag);//recursive call to remove all children of that child
446        }
447        delete matInfo[childEndtag]; //make sure this location is never accessed again.
448
449        $("#solver" + childEndtag).remove();//remove that child itself
450    }
451
452    //adjust variables in matInfo
453    if(matInfo[endtag].pc_type == "mg") {
454        matInfo[endtag].pc_mg_levels = 0;
455    }
456    else if(matInfo[endtag].pc_type == "fieldsplit") {
457        matInfo[endtag].pc_fieldsplit_blocks = 0;
458    }
459
460    $("#pc_type" + endtag).nextAll().remove();//remove the options in the same level solver
461
462}
463
464//called when text input for pc_fieldsplit_blocks is changed
465$(document).on('keyup', "input[id^='pc_fieldsplit_blocks']", function() {
466
467    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
468        return;
469
470    var id     = this.id;
471    var endtag = id.substring(id.indexOf(0),id.length);
472    var val    = $(this).val();
473
474    // this next part is a bit tricky...there are 2 cases
475
476    //case 1: we need to remove some divs
477    if(val < matInfo[endtag].pc_fieldsplit_blocks) {
478        for(var i=val; i<matInfo[endtag].pc_fieldsplit_blocks; i++) {
479            var childEndtag = endtag + "_" + i;
480            removeAllChildren(childEndtag); //remove grandchildren (if any)
481            delete matInfo[childEndtag];
482            $("#solver" + childEndtag).remove(); //remove the divs
483        }
484        matInfo[endtag].pc_fieldsplit_blocks = val;
485    }
486
487    //case 2: we need to add some divs
488    else if(val > matInfo[endtag].pc_fieldsplit_blocks) {
489
490        var defaults = getDefaults("fieldsplit",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
491
492        for(var i = matInfo[endtag].pc_fieldsplit_blocks; i < val; i++) {
493
494            //add divs and write matInfo
495            var childEndtag = endtag + "_" + i;
496            var margin = getNumUnderscores(childEndtag) * 30;
497
498            //this is the trickiest part: need to find exactly where to insert the new divs
499            //find the first div that doesn't begin with endtag
500
501            var currentDiv  = $(this).parent().get(0);
502
503            while($(currentDiv).next().length > 0) { //while has next
504                var nextDiv    = $(currentDiv).next().get(0);
505                var nextId     = nextDiv.id;
506                var nextEndtag = nextDiv.id.substring(nextId.indexOf("0"),nextId.length);
507
508                if(nextEndtag.indexOf(endtag) == 0) {
509                    currentDiv = nextDiv;
510                }
511                else
512                    break;
513            }
514
515            //append new stuff immediately after current div
516            matInfo[childEndtag] = {
517                pc_type : defaults.sub_pc_type,
518                ksp_type: defaults.sub_ksp_type,
519                symm: matInfo[endtag].symm, //inherit!!
520                posdef: matInfo[endtag].posdef,
521                logstruc: false
522            };
523
524            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
525            $(currentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
526            $("#solver" + childEndtag).append("<br><b>Fieldsplit " + i + " Options (Matrix is <input type=\"checkbox\" id=\"symm" + childEndtag + "\">symmetric, <input type=\"checkbox\" id=\"posdef" + childEndtag + "\">positive definite, <input type=\"checkbox\" id=\"logstruc" + childEndtag + "\">block structured)</b>");
527
528            //special for fieldsplit
529            if(matInfo[childEndtag].symm)
530                $("#symm" + childEndtag).attr("checked",true);
531            if(matInfo[childEndtag].posdef)
532                $("#posdef" + childEndtag).attr("checked",true);
533            if(matInfo[childEndtag].logstruc)
534                $("#logstruc" + childEndtag).attr("checked",true);
535
536            if(matInfo[endtag].symm)
537                $("#symm" + childEndtag).attr("disabled",true);
538            if(matInfo[endtag].posdef)
539                $("#posdef" + childEndtag).attr("disabled",true);
540            if(!matInfo[endtag].symm)
541                $("#posdef" + childEndtag).attr("disabled",true);
542
543            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
544	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
545
546            populateList("ksp",childEndtag);
547            populateList("pc",childEndtag);
548
549            //set defaults
550            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
551	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
552            //trigger both to add additional options
553            $("#ksp_type" + childEndtag).trigger("change");
554            $("#pc_type" + childEndtag).trigger("change");
555        }
556        matInfo[endtag].pc_fieldsplit_blocks = val;
557    }
558    refresh(); //refresh diagrams
559});
560
561/*
562  This function is called when the text input "MG Levels" is changed
563*/
564$(document).on('keyup', "input[id^='pc_mg_levels']", function()
565{
566    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
567        return;
568
569    var id     = this.id;
570    var endtag = id.substring(id.indexOf(0),id.length);
571    var val    = $(this).val();
572
573    // this next part is a bit tricky...there are 2 cases
574
575    //case 1: we need to remove some divs
576    if(val < matInfo[endtag].pc_mg_levels) {
577        for(var i=val; i<matInfo[endtag].pc_mg_levels; i++) {
578            var childEndtag = endtag + "_" + i;
579            removeAllChildren(childEndtag); //remove grandchildren (if any)
580            delete matInfo[childEndtag];
581            $("#solver" + childEndtag).remove(); //remove the divs
582        }
583        matInfo[endtag].pc_mg_levels = val;
584    }
585
586    //case 2: we need to add some divs
587    else if(val > matInfo[endtag].pc_mg_levels) {
588
589        var defaults = getDefaults("mg",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
590
591        for(var i = matInfo[endtag].pc_mg_levels; i < val; i++) {
592            var childEndtag = endtag + "_" + i;
593            var margin = getNumUnderscores(childEndtag) * 30;
594
595            //this is the trickiest part: need to find exactly where to insert the new divs
596            //find the first div that doesn't begin with endtag
597
598            var currentDiv  = $(this).parent().get(0);
599
600            while($(currentDiv).next().length > 0) { //while has next
601                var nextDiv    = $(currentDiv).next().get(0);
602                var nextId     = nextDiv.id;
603                var nextEndtag = nextDiv.id.substring(nextId.indexOf("0"),nextId.length);
604
605                if(nextEndtag.indexOf(endtag) == 0) {
606                    currentDiv = nextDiv;
607                }
608                else
609                    break;
610            }
611
612            //append new stuff immediately after current div
613            matInfo[childEndtag] = {
614                pc_type : defaults.sub_pc_type,
615                ksp_type: defaults.sub_ksp_type,
616                symm: matInfo[endtag].symm, //inherit!!
617                posdef: matInfo[endtag].posdef,
618                logstruc: matInfo[endtag].logstruc
619            };
620
621            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
622            $(currentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
623            if(i == 0) //coarse grid solver (level 0)
624                $("#solver" + childEndtag).append("<br><b>Coarse Grid Solver (Level 0)  </b>");
625            else
626                $("#solver" + childEndtag).append("<br><b>Smoothing (Level " + i + ")  </b>");
627
628            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
629	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
630
631            populateList("ksp",childEndtag);
632            populateList("pc",childEndtag);
633
634            //set defaults
635            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
636	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
637            //trigger both to add additional options
638            $("#ksp_type" + childEndtag).trigger("change");
639            $("#pc_type" + childEndtag).trigger("change");
640        }
641        matInfo[endtag].pc_mg_levels = val;
642    }
643    refresh(); //refresh diagrams
644});
645
646$(document).on('keyup', "input[id^='pc_gamg_levels']", function()
647{
648    if($(this).val().match(/[^0-9]/) || $(this).val()<1) //return on invalid input
649        return;
650
651    var id     = this.id;
652    var endtag = id.substring(id.indexOf(0),id.length);
653    var val    = $(this).val();
654
655    // this next part is a bit tricky...there are 2 cases
656
657    //case 1: we need to remove some divs
658    if(val < matInfo[endtag].pc_gamg_levels) {
659        for(var i=val; i<matInfo[endtag].pc_gamg_levels; i++) {
660            var childEndtag = endtag + "_" + i;
661            removeAllChildren(childEndtag); //remove grandchildren (if any)
662            delete matInfo[childEndtag];
663            $("#solver" + childEndtag).remove(); //remove the divs
664        }
665        matInfo[endtag].pc_gamg_levels = val;
666    }
667
668    //case 2: we need to add some divs
669    else if(val > matInfo[endtag].pc_gamg_levels) {
670
671        var defaults = getDefaults("gamg",matInfo[endtag].symm,matInfo[endtag].posdef,matInfo[endtag].logstruc);
672
673        for(var i = matInfo[endtag].pc_gamg_levels; i < val; i++) {
674            var childEndtag = endtag + "_" + i;
675            var margin = getNumUnderscores(childEndtag) * 30;
676
677            //this is the trickiest part: need to find exactly where to insert the new divs
678            //find the first div that doesn't begin with endtag
679
680            var currentDiv  = $(this).parent().get(0);
681
682            while($(currentDiv).next().length > 0) { //while has next
683                var nextDiv    = $(currentDiv).next().get(0);
684                var nextId     = nextDiv.id;
685                var nextEndtag = nextDiv.id.substring(nextId.indexOf("0"),nextId.length);
686
687                if(nextEndtag.indexOf(endtag) == 0) {
688                    currentDiv = nextDiv;
689                }
690                else
691                    break;
692            }
693
694            //append new stuff immediately after current div
695            matInfo[childEndtag] = {
696                pc_type : defaults.sub_pc_type,
697                ksp_type: defaults.sub_ksp_type,
698                symm: matInfo[endtag].symm, //inherit!!
699                posdef: matInfo[endtag].posdef,
700                logstruc: matInfo[endtag].logstruc
701            };
702
703            var margin = 30 * getNumUnderscores(childEndtag);  //indent based on the level of the solver (number of underscores)
704            $(currentDiv).after("<div id=\"solver" + childEndtag + "\" style=\"margin-left:" + margin + "px;\"></div>");
705            if(i == 0) //coarse grid solver (level 0)
706                $("#solver" + childEndtag).append("<br><b>Coarse Grid Solver (Level 0)  </b>");
707            else
708                $("#solver" + childEndtag).append("<br><b>Smoothing (Level " + i + ")  </b>");
709
710            $("#solver" + childEndtag).append("<br><b>KSP &nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"ksp_type" + childEndtag  + "\"></select>");
711	    $("#solver" + childEndtag).append("<br><b>PC  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b><select id=\"pc_type" + childEndtag + "\"></select>");
712
713            populateList("ksp",childEndtag);
714            populateList("pc",childEndtag);
715
716            //set defaults
717            $("#ksp_type" + childEndtag).val(defaults.sub_ksp_type);
718	    $("#pc_type" + childEndtag).val(defaults.sub_pc_type);
719            //trigger both to add additional options
720            $("#ksp_type" + childEndtag).trigger("change");
721            $("#pc_type" + childEndtag).trigger("change");
722        }
723        matInfo[endtag].pc_gamg_levels = val;
724    }
725    refresh(); //refresh diagrams
726});
727