/*
This file is part of the FElt finite element analysis package.
Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
# include <stdio.h>
# include <unistd.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Xaw/Simple.h>
# include "Canvas.h"
# include "Element.h"
# include "Node.h"
# include "Solution.h"
# include "allocate.h"
# include "problem.h"
# include "globals.h"
# include "Drawing.h"
# include "vfe.h"
# include "procedures.h"
# include "error.h"
extern ElementDialog element_d;
extern NodeDialog node_d;
/****************************************************************************
* Functions: BuildNodeArray and BuildElementArray
*
* Description: These are two tree iterators that build the node and element
* arrays from the node and element trees
****************************************************************************/
static unsigned array_count;
static int BuildNodeArray (item)
Item item;
{
FigureAttributes attr;
char buffer [10];
Node node;
Drawn drawn;
node = (Node) item;
problem.nodes [++array_count] = node;
if (array_count != node -> number) {
node -> number = array_count;
drawn = (Drawn) node -> aux;
if (drawn -> label != NULL) {
sprintf (attr.text = buffer, " %d", node -> number);
DW_SetAttributes (drawing, drawn -> label, DW_FigureText, &attr);
}
}
return 0;
}
static int BuildElementArray (item)
Item item;
{
FigureAttributes attr;
char buffer [10];
Element element;
Drawn drawn;
element = (Element) item;
problem.elements [++array_count] = element;
if (array_count != element -> number) {
element -> number = array_count;
drawn = (Drawn) element -> aux;
if (drawn -> label != NULL) {
ComputeCenter (element, &attr.x, &attr.y);
sprintf (attr.text = buffer, "%d", element -> number);
DW_SetAttributes (drawing, drawn -> label, DW_FigureText |
DW_FigureLocation, &attr);
}
}
return 0;
}
/****************************************************************************
*
* Function: SolveProblem
*
* Description: Basically main from the Felt application ... pretty
* straightforward
*
***************************************************************************/
int SolveProblem ( )
{
unsigned numnodes; /* total number of nodes */
unsigned numelts; /* total number of elements */
Node *node; /* the array of nodes */
Element *element; /* array of elements */
Matrix K, /* global stiffness matrix */
Kcond; /* condensed stiffness matrix */
Matrix M, C;
Matrix Ccond;
Matrix Mcond; /* condensed mass matrix */
Matrix Mm, Cm, Km;
Matrix *H; /* matrix of transfer functions */
Matrix S;
Vector F, /* force vector */
Fcond, /* condensed force vector */
d; /* displacement vector */
Matrix x; /* eigenvectors */
Vector lambda; /* eigenvalues */
unsigned numforced;
NodeDOF *forced;
int status; /* return status */
Reaction *R; /* reaction force vector */
unsigned numreactions; /* the number of reactions */
char *temp_out;
FILE *output;
unsigned *old_numbers;
Matrix dtable;
Matrix ttable;
int error_flag;
unsigned i;
AnalysisType mode;
/*
* make sure the node and element numbering doesn't have any gaps
* and set-up the node and element arrays
*/
numnodes = CompactNodeNumbers ( );
numelts = CompactElementNumbers ( );
node = problem.nodes;
element = problem.elements;
mode = SetAnalysisMode ( );
if (numnodes == 0 || numelts == 0) {
error ("nothing to do!");
return 1;
}
ClearNodes ( );
/*
* create a temporary file for output
*/
#ifdef _CONVEX_SOURCE
temp_out = tmpnam ("velv");
#else
temp_out = tempnam (NULL,"velv");
#endif
output = fopen (temp_out,"w");
if (output == NULL) {
error ("Could not open temporary file for output.");
return 1;
}
/*
* generate a debug file if requested
*/
if (solution -> debug)
fWriteFeltFile (output);
/*
* set the details stream if needed
*/
if (solution -> details)
SetDetailStream (output);
else
SetDetailStream (NULL);
/*
* initialize all these so we won't have trouble destroying them
* if they never actually get allocated
*/
K = Kcond = Km = C = Ccond = Cm = M = Mcond = Mm = NullMatrix;
x = NullMatrix;
dtable = ttable = S = NullMatrix;
H = NULL;
F = Fcond = d = lambda = NullVector;
/*
* find the active DOFs and renumber the nodes if desired (common
* steps in all problem modes
*/
FindDOFS ( );
if (solution -> renumber)
old_numbers = RenumberNodes (node, element, numnodes, numelts);
else
old_numbers = NULL;
error_flag = 0;
/*
* switch on the problem mode depending on whether we not a
* static and transient analysis
*/
switch (mode) {
case Transient:
status = CheckAnalysisParameters (Transient);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
status = ConstructDynamic (&K, &M, &C);
if (status) {
error ("%d errors in stiffness and mass definitions.", status);
error_flag = 1;
break;
}
if (solution -> matrices)
PrintGlobalMatrices (output, M, C, K);
if (analysis.step == 0.0)
dtable = IntegrateHyperbolicDE (K, M, C);
else
dtable = RosenbrockHyperbolicDE (K, M, C, &ttable);
if (dtable == NullMatrix) {
error ("could not perform integration - probably a singularity.");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
WriteTransientTable (dtable, ttable, output);
if (solution -> plot)
VelvetPlotTD (dtable, ttable, "time", "dx", "Nodal Time-Displacement", True);
break;
case Spectral:
status = CheckAnalysisParameters (Spectral);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
status = ConstructDynamic (&K, &M, &C);
if (status) {
error ("%d errors in stiffness and mass definitions.", status);
error_flag = 1;
break;
}
ZeroConstrainedDOF (K, NullMatrix, &Kcond, NULL);
ZeroConstrainedDOF (M, NullMatrix, &Mcond, NULL);
ZeroConstrainedDOF (C, NullMatrix, &Ccond, NULL);
if (solution -> matrices)
PrintGlobalMatrices (output, Mcond, Ccond, Kcond);
FindForcedDOF (&forced, &numforced);
H = ComputeTransferFunctions (Mcond, Ccond, Kcond, forced, numforced);
if (!solution -> transfer)
S = ComputeOutputSpectra (H, forced, numforced);
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
if (solution -> transfer) {
WriteTransferFunctions (H, forced, numforced, output);
if (solution -> plot)
VelvetPlotTransferFunctions (H, forced, numforced,
"frequency", "H",
"Spectral Transfer Function");
break;
}
WriteOutputSpectra (S, output);
if (solution -> plot)
VelvetPlotSpectra (S, "frequency", "S", "Output Power Spectra", True);
break;
case Static:
K = ConstructStiffness (&status);
if (status) {
error ("%d fatal errors in element stiffness definitions.", status);
error_flag = 1;
break;
}
if (solution -> matrices)
PrintGlobalMatrices (output, NullMatrix, NullMatrix, K);
F = ConstructForceVector ( );
ZeroConstrainedDOF (K, F, &Kcond, &Fcond);
/*
* the result will not have new space - it will get returned
* in the same space that Fcond used to occupy ...
*/
d = SolveForDisplacements (Kcond, Fcond);
if (d == NullVector) {
error ("singluarity in final system of equations - cannot proceed.");
error_flag = 1;
break;
}
numreactions = SolveForReactions (K, d, old_numbers, &R);
status = ElementStresses ( );
if (status) {
error ("%d errors found computing element stresses.",status);
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
WriteStructuralResults (output, solution -> title, R, numreactions);
if (numreactions) {
for (i = 1; i <= numreactions; i ++)
XtFree ((char *) R [i]);
XtFree ((char *) (R + 1));
}
break;
case StaticLoadCases:
case StaticLoadRange:
status = CheckAnalysisParameters (mode);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
K = ConstructStiffness(&status);
if (status) {
error ("%d fatal errors in element stiffness definitions.", status);
error_flag = 1;
break;
}
if (solution -> matrices)
PrintGlobalMatrices (output, NullMatrix, NullMatrix, K);
F = ConstructForceVector ( );
ZeroConstrainedDOF (K, F, &Kcond, &Fcond);
if (mode == StaticLoadCases)
dtable = SolveStaticLoadCases (Kcond, Fcond);
else
dtable = SolveStaticLoadRange (Kcond, Fcond);
if (dtable == NullMatrix) {
error ("could not solve for global displacements.");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (problem.nodes, old_numbers, problem.num_nodes);
if (mode == StaticLoadCases)
WriteLoadCaseTable (dtable, output);
else
WriteLoadRangeTable (dtable, output);
if (solution -> plot && mode == StaticLoadRange)
VelvetPlotLoadRange (dtable);
break;
case StaticSubstitutionLoadRange:
case StaticIncrementalLoadRange:
status = CheckAnalysisParameters (StaticSubstitution);
status += CheckAnalysisParameters (StaticLoadRange);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
K = CreateNonlinearStiffness (&status);
if (status) {
error ("could not create nonlinear stiffness matrix");
error_flag = 1;
break;
}
F = ConstructForceVector ( );
if (mode == StaticSubstitutionLoadRange)
dtable = SolveNonlinearLoadRange (K, F, 0);
else
dtable = SolveNonlinearLoadRange (K, F, 0); /* should be 1 */
if (dtable == NullMatrix) {
error ("did not converge on a solution");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (problem.nodes, old_numbers, problem.num_nodes);
WriteLoadRangeTable (dtable, output);
if (solution -> plot)
VelvetPlotLoadRange (dtable);
break;
case StaticSubstitution:
case StaticIncremental:
status = CheckAnalysisParameters (mode);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
K = CreateNonlinearStiffness (&status);
if (status) {
error ("could not create nonlinear stiffness matrix");
error_flag = 1;
break;
}
F = ConstructForceVector ( );
if (mode == StaticSubstitution)
d = StaticNonlinearDisplacements (K, F, 0);
else
d = StaticNonlinearDisplacements (K, F, 0); /* should be 1 */
if (d == NullMatrix) {
error ("did not converge on a solution");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (problem.nodes, old_numbers, problem.num_nodes);
WriteStructuralResults (output, solution -> title, NULL, 0);
break;
case Modal:
status = CheckAnalysisParameters (Modal);
if (status) {
error ("%d errors found in analysis parameters.", status);
error_flag = 1;
break;
}
status = ConstructDynamic (&K, &M, &C);
if (status) {
error ("%d errors in stiffness and mass definitions.", status);
error_flag = 1;
break;
}
RemoveConstrainedDOF (K, M, C, &Kcond, &Mcond, &Ccond);
if (solution -> matrices)
PrintGlobalMatrices (output, Mcond, Ccond, Kcond);
status = ComputeEigenModes (Kcond, Mcond, &lambda, &x);
if (status == M_NOTPOSITIVEDEFINITE) {
error ("coefficient matrix is not positive definite.");
error_flag = 1;
break;
}
else if (status) {
error ("error computing eigenmodes (report status code %d).", status);
error_flag = 1;
break;
}
if (solution -> mode_shapes) {
dtable = ModalNodalDisplacements (x);
SetupModeShapes (dtable, lambda);
}
NormalizeByFirst (x, x);
WriteEigenResults (lambda, x, solution -> title, output);
if (!solution -> eigen) {
FormModalMatrices (x, Mcond, Ccond, Kcond, &Mm, &Cm, &Km, solution -> orthonormal);
WriteModalResults (output, Mm, Cm, Km, lambda);
}
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
break;
case TransientThermal:
analysis.dofs [1] = Tx;
analysis.numdofs = 1;
status = CheckAnalysisParameters (TransientThermal);
if (status) {
error ("%d Errors found in analysis parameters.", status);
error_flag = 1;
break;
}
status = ConstructDynamic (&K, &M, &C);
if (status) {
error ("%d errors in stiffness and mass definitions.", status);
error_flag = 1;
break;
}
if (solution -> matrices)
PrintGlobalMatrices (output, M, NullMatrix, K);
dtable = IntegrateParabolicDE (K, M);
if (dtable == NullMatrix) {
error ("could not perform integration - probably a singularity.");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
WriteTransientTable (dtable, NullMatrix, output);
if (solution -> plot)
VelvetPlotTD (dtable, NullMatrix, "time", "T", "Nodal Time-Temperature", False);
break;
case StaticThermal:
K = ConstructStiffness(&status);
if (status)
Fatal ("%d Fatal errors in element stiffness definitions", status);
if (solution -> matrices)
PrintGlobalMatrices (output, NullMatrix, NullMatrix, K);
F = ConstructForceVector ( );
ZeroConstrainedDOF (K, F, &Kcond, &Fcond);
d = SolveForDisplacements (Kcond, Fcond);
if (d == NullVector) {
error ("singluarity in final system of equations - cannot proceed.");
error_flag = 1;
break;
}
if (old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
WriteTemperatureResults (output, problem.title);
break;
}
if (error_flag && old_numbers != NULL)
RestoreNodeNumbers (node, old_numbers, numnodes);
if (!error_flag && solution -> summary)
WriteMaterialStatistics (output);
if (dtable != NullMatrix)
DestroyMatrix (dtable);
if (ttable != NullMatrix)
DestroyMatrix (ttable);
if (K != NullMatrix)
DestroyMatrix (K);
if (M != NullMatrix)
DestroyMatrix (M);
if (C != NullMatrix)
DestroyMatrix (C);
if (F != NullVector)
DestroyVector (F);
if (Kcond != NullMatrix)
DestroyMatrix (Kcond);
if (Mcond != NullMatrix)
DestroyMatrix (Mcond);
if (Ccond != NullMatrix)
DestroyMatrix (Ccond);
if (Km != NullMatrix)
DestroyMatrix (Km);
if (Mm != NullMatrix)
DestroyMatrix (Mm);
if (Cm != NullMatrix)
DestroyMatrix (Cm);
if (x != NullMatrix)
DestroyMatrix (x);
if (lambda != NullVector)
DestroyVector (lambda);
if (d == NullVector && Fcond != NullVector)
DestroyVector (Fcond);
else if (d != NullVector)
DestroyVector (d);
if (old_numbers) {
ZeroOffset (old_numbers);
Deallocate (old_numbers);
}
fclose (output);
if (error_flag)
return 1;
if (solution -> felt)
OutputDialogView (output_dialog, temp_out, 20, 80);
unlink (temp_out);
XtFree ((char *) temp_out);
if (solution -> felt)
OutputWindowPopup ( );
if (solution -> stress)
SetupStresses (False);
if (solution -> displacement)
SetupDisplacements (False);
if (solution -> structure)
SetupStructure (False);
return 0;
}
int CompactNodeNumbers ( )
{
unsigned numnodes;
numnodes = TreeSize (problem.node_tree);
if (numnodes == 0)
return problem.num_nodes = 0;
/*
* build the array of _consecutive_ pointers to nodes by
* creating new space for it and then iterating on the tree
*/
if (problem.nodes) {
ZeroOffset (problem.nodes);
Deallocate (problem.nodes);
}
problem.nodes = Allocate (Node, numnodes);
UnitOffset (problem.nodes);
DW_SetAutoRedraw (drawing, False);
array_count = 0;
TreeSetIterator (problem.node_tree, BuildNodeArray);
TreeIterate (problem.node_tree);
if (canvas -> node_numbers)
DW_SetAutoRedraw (drawing, True);
return problem.num_nodes = numnodes;
}
int CompactElementNumbers ( )
{
unsigned numelts;
numelts = TreeSize (problem.element_tree);
if (numelts == 0)
return problem.num_elements = 0;
if (problem.elements) {
ZeroOffset (problem.elements);
Deallocate (problem.elements);
}
problem.elements = Allocate (Element, numelts);
UnitOffset (problem.elements);
DW_SetAutoRedraw (drawing, False);
array_count = 0;
TreeSetIterator (problem.element_tree, BuildElementArray);
TreeIterate (problem.element_tree);
if (canvas -> element_numbers)
DW_SetAutoRedraw (drawing, True);
return problem.num_elements = numelts;
}
void SetupAndSolve ( )
{
SetWaitCursor (drawing);
BufferErrors (True);
SolveProblem ( );
BufferErrors (False);
NodeDialogDisplay (node_d, NodeDialogActive (node_d));
ElementDialogDisplay (element_d, ElementDialogActive (element_d));
SetNormalCursor (drawing);
}
void SetupAnimate ( )
{
int status1, status2;
unsigned i,j;
unsigned count;
unsigned dofs [7];
Matrix M, C, K;
unsigned numnodes, numelts;
Matrix dtable;
unsigned *old_numbers;
Node *anodes;
char adofs [7];
unsigned anumnodes;
unsigned anumdofs;
double z_plane;
Boolean draw3d;
if (problem.mode != Transient) {
error ("problem mode must be transient for animation\n");
return;
}
BufferErrors (True);
numnodes = CompactNodeNumbers ( );
if (numnodes == 0)
return;
numelts = CompactElementNumbers ( );
if (numelts == 0)
return;
SetWaitCursor (drawing);
draw3d = False;
z_plane = problem.elements[1] -> node[1] -> z;
for (i = 1; i <= numelts ; i++) {
for (j=1 ; j <= problem.elements[i] -> definition -> shapenodes ; j++) {
if (problem.elements[i] -> node[j] -> z != z_plane) {
draw3d = True;
break;
}
}
if (draw3d)
break;
}
anumdofs = analysis.numdofs;
for (i = 1 ; i <= analysis.numdofs ; i++)
adofs [i] = analysis.dofs [i];
anodes = analysis.nodes;
analysis.nodes = problem.nodes;
anumnodes = analysis.numnodes;
analysis.numnodes = numnodes;
if (draw3d) {
analysis.numdofs = 3;
analysis.dofs [1] = Tx;
analysis.dofs [2] = Ty;
analysis.dofs [3] = Tz;
}
else {
analysis.numdofs = 2;
analysis.dofs [1] = Tx;
analysis.dofs [2] = Ty;
}
if (solution -> renumber)
old_numbers = RenumberNodes (problem.nodes, problem.elements,
numnodes, numelts);
else
old_numbers = NULL;
K = M = C = dtable = NullMatrix;
count = FindDOFS (problem.elements, numelts, dofs);
status1 = CheckAnalysisParameters (Transient);
status2 = 0;
if (!status1)
status2 = ConstructDynamic (&K, &M, &C);
if (status1 || status2)
error ("errors found - could not animate.");
else {
dtable = IntegrateHyperbolicDE (K, M, C);
if (draw3d)
AnimateStructure3D (dtable, problem.nodes, problem.elements,
numnodes, numelts);
else
AnimateStructure (dtable, problem.nodes, problem.elements,
numnodes, numelts);
if (old_numbers)
RestoreNodeNumbers (problem.nodes, old_numbers, numnodes);
}
analysis.nodes = anodes;
analysis.numnodes = anumnodes;
analysis.numdofs = anumdofs;
for (i = 1 ; i <= analysis.numdofs ; i++)
analysis.dofs [i] = adofs [i];
if (old_numbers) {
ZeroOffset (old_numbers);
Deallocate (old_numbers);
}
if (K != NullMatrix)
DestroyVector (K);
if (M != NullMatrix)
DestroyVector (M);
if (C != NullMatrix)
DestroyVector (C);
if (dtable != NullMatrix)
DestroyMatrix (dtable);
BufferErrors (False);
SetNormalCursor (drawing);
return;
}
void SetupStresses (build_elt)
Boolean build_elt;
{
Element *e;
unsigned numelts;
unsigned nd,i,j;
int depth;
Arg arglist [1];
int flag;
/*
* technically someone on a 1-bit screen should never get here ...
* but just to be sure.
*/
XtSetArg (arglist[0], XtNdepth, &depth);
XtGetValues (toplevel, arglist, 1);
if (depth < 8) {
error ("you must have a > 8-bit deep screen to do stress plots");
return;
}
if (build_elt)
numelts = CompactElementNumbers ( );
else
numelts = problem.num_elements;
if (numelts == 0)
return;
e = problem.elements;
nd = 0;
flag = 1;
for (i = 1; i <= numelts ; i++) {
if (e [i] -> node [1] -> stress == NULL) {
error ("could not get nodally averaged stresses for all elements");
return;
}
if (solution -> s_component > e [i] -> definition -> numstresses) {
error ("invalid stress component for element %d",i);
return;
}
if (flag) {
for (j = 1 ; j <= e [i] -> ninteg ; j++) {
if (e [i] -> stress [j] ->
values [solution -> s_component] != 0)
flag = 0;
}
}
nd += problem.elements[i] -> ninteg;
}
if (flag) {
error ("all stresses are zero for specified component");
return;
}
SetWaitCursor (drawing);
CreateOpenGLShell("stressShell", "Stress Plot", True,
solution -> s_component, e, numelts, True);
SetNormalCursor (drawing);
return;
}
void SetupDisplacements (build_arrays)
Boolean build_arrays;
{
unsigned numnodes;
unsigned numelts;
unsigned i;
unsigned flag;
int depth;
Arg arglist [1];
XtSetArg (arglist[0], XtNdepth, &depth);
XtGetValues (toplevel, arglist, 1);
if (depth < 8) {
error ("you must have a > 8-bit deep screen to do displacement plots");
return;
}
if (build_arrays) {
numelts = CompactElementNumbers ( );
numnodes = CompactNodeNumbers ( );
}
else {
numelts = problem.num_elements;
numnodes = problem.num_nodes;
}
if (numelts == 0 || numnodes == 0)
return;
flag = 1;
for (i = 1 ; i <= numnodes ; i++) {
if (problem.nodes [i] -> dx [solution -> d_component] != 0) {
flag = 0;
break;
}
}
if (flag) {
error ("all displacements are zero for specified component");
return;
}
SetWaitCursor (drawing);
CreateOpenGLShell("displShell", "Displacement Plot", False,
solution -> d_component, problem.elements, numelts, True);
SetNormalCursor (drawing);
return;
}
void SetupModeShapes (phi, lambda)
Matrix phi;
Matrix lambda;
{
unsigned i,j;
double z_plane;
Boolean draw3d;
unsigned numelts;
numelts = problem.num_elements;
draw3d = False;
z_plane = problem.elements[1] -> node[1] -> z;
for (i = 1; i <= numelts ; i++) {
for (j = 1 ; j <= problem.elements[i] -> definition -> shapenodes ; j++) {
if (problem.elements[i] -> node[j] -> z != z_plane) {
draw3d = True;
break;
}
}
if (draw3d)
break;
}
if (draw3d)
DrawModeShapes3D (phi, lambda, problem.nodes, problem.elements,
problem.num_nodes, problem.num_elements);
else
DrawModeShapes (phi, lambda, problem.nodes, problem.elements,
problem.num_nodes, problem.num_elements);
return;
}
void SetupStructure (build_elt)
Boolean build_elt;
{
unsigned i,j;
double z_plane;
unsigned numelts;
if (build_elt)
numelts = CompactElementNumbers ( );
else
numelts = problem.num_elements;
if (numelts == 0)
return;
CreateOpenGLShell("structShell", "Structure Plot", False, 0,
problem.elements, numelts, False);
}
void OptimizeNumbering ( )
{
char buffer [10];
FigureAttributes attr;
unsigned numnodes, numelts;
unsigned i;
Drawn drawn;
Node node;
numnodes = CompactNodeNumbers ( );
if (numnodes == 0)
return;
numelts = CompactElementNumbers ( );
if (numelts == 0)
return;
for (i = 1 ; i <= numnodes ; i++)
TreeDelete (problem.node_tree, problem.nodes [i]);
(unsigned *) RenumberNodes (problem.nodes, problem.elements,
numnodes, numelts);
DW_SetAutoRedraw (drawing, False);
for (i = 1 ; i <= numnodes ; i++) {
node = problem.nodes [i];
TreeInsert (problem.node_tree, node);
drawn = (Drawn) (node -> aux);
if (drawn -> label != NULL) {
sprintf (attr.text = buffer, " %d", node -> number);
DW_SetAttributes (drawing, drawn -> label, DW_FigureText, &attr);
}
}
if (canvas -> node_numbers)
DW_SetAutoRedraw (drawing, True);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1