# include # include # include # include "ppc_fetch_line.h" # include "ppc_ll.h" # include "ppc_truss.h" # include "ppc_truss_io.h" # include "ppc_xmalloc.h" # define BUFLEN 128 # define SQ(x) ((x)*(x)) void free_links_list ( conscell *links ); void free_nodes_list ( conscell *nodes ); void free_truss ( struct truss *truss ); conscell *get_links ( FILE *stream, int *lineno, conscell *nodes_list ); int get_loads ( FILE *stream, int *lineno, conscell *nodes_list ); conscell *get_nodes ( FILE *stream, int *lineno ); struct link *make_link ( int n, int n1, int n2, double A, double E, conscell *nodes_list ); struct node *make_node ( int n, double x, double y, int xfixed, int yfixed ); struct link *process_link_line ( char *str, conscell *nodes_list ); int process_load_line ( char *str, conscell *nodes_list ); struct node *process_node_line ( char *str ); struct truss *read_truss ( FILE *stream ); void write_truss ( struct truss *truss, char *filename ); /******************************************************************************/ void free_links_list ( conscell *links ) /******************************************************************************/ /* Purpose: free_links_list() frees the memory associated with a link list. Licensing: This code is distributed under the MIT license. Modified: 17 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { conscell *p; /* Traverse the list, freeing the data. */ for ( p = links; p != NULL; p = p->next ) { struct link *link = p->data; free ( link ); } /* Now free the list. */ ll_free ( links ); return; } /******************************************************************************/ void free_nodes_list ( conscell *nodes ) /******************************************************************************/ /* Purpose: free_nodes_list() frees the memory associated with a node list. Licensing: This code is distributed under the MIT license. Modified: 16 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { conscell *p; /* Traverse the list, freeing the data. */ for ( p = nodes; p != NULL; p = p->next ) { struct node *node = p->data; free ( node ); } /* Now free the list. */ ll_free ( nodes ); return; } /******************************************************************************/ void free_truss ( struct truss *truss ) /******************************************************************************/ /* Purpose: free_truss() frees the memory associated with a truss structure. Licensing: This code is distributed under the MIT license. Modified: 16 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { free_nodes_list ( truss->nodes_list ); free_links_list ( truss->links_list ); free ( truss ); return; } /******************************************************************************/ conscell *get_links ( FILE *stream, int *lineno, conscell *nodes_list ) /******************************************************************************/ /* Purpose: get_links() reads link information from a truss structure file. Licensing: This code is distributed under the MIT license. Modified: 26 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { char buf[BUFLEN]; conscell *links_list = NULL; struct link *link; char *str; if ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_links(): Fatal error!\n" ); fprintf ( stderr, " No link data in input.\n" ); return NULL; } /* strcmp(s1,s2) is 0 if strings s1 and s2 are equal. */ if ( strcmp ( str, "begin links" ) != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_links(): Fatal error!\n" ); fprintf ( stderr, " No 'begin links' in input.\n" ); return NULL; } while ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) != NULL ) { if ( strcmp ( str, "end links" ) == 0 ) { return links_list; } /* Try to read another link. */ if ( ( link = process_link_line ( str, nodes_list ) ) == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_links(): Fatal error!\n" ); fprintf ( stderr, " Bad input on line %d.\n", *lineno ); free_links_list ( links_list ); return NULL; } /* Add link to list. */ links_list = ll_push ( links_list, link ); } /* An error if we reached the end of input without an "end nodes" line. */ fprintf ( stderr, "\n" ); fprintf ( stderr, "get_links(): Fatal error!\n" ); fprintf ( stderr, " No 'end links' in input.\n" ); free_links_list ( links_list ); return NULL; } /******************************************************************************/ int get_loads ( FILE *stream, int *lineno, conscell *nodes_list ) /******************************************************************************/ /* Purpose: get_loads() reads load information from a truss structure file. Licensing: This code is distributed under the MIT license. Modified: 24 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { char buf[BUFLEN]; char *str; if ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_loads(): Fatal error!\n" ); fprintf ( stderr, " No load data in input.\n" ); return 0; } /* strcmp(s1,s2) is 0 if strings s1 and s2 are equal. */ if ( strcmp ( str, "begin loads" ) != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_loads(): Fatal error!\n" ); fprintf ( stderr, " No 'begin loads' in input.\n" ); return 0; } while ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) != NULL ) { if ( strcmp ( str, "end loads" ) == 0 ) { return 1; } /* Try to read another load. */ if ( ! process_load_line ( str, nodes_list ) ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_loads(): Fatal error!\n" ); fprintf ( stderr, " Bad input on line %d.\n", *lineno ); return 0; } } /* An error if we reached the end of input without an "end loads" line. */ fprintf ( stderr, "\n" ); fprintf ( stderr, "get_loads(): Fatal error!\n" ); fprintf ( stderr, " No 'end loads' in input.\n" ); return 0; } /******************************************************************************/ conscell *get_nodes ( FILE *stream, int *lineno ) /******************************************************************************/ /* Purpose: get_nodes() reads node information from a truss structure file. Licensing: This code is distributed under the MIT license. Modified: 16 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { char buf[BUFLEN]; struct node *node; conscell *nodes_list = NULL; char *str; if ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_nodes(): Fatal error!\n" ); fprintf ( stderr, " No node data in input.\n" ); return NULL; } /* strcmp(s1,s2) is 0 if strings s1 and s2 are equal. */ if ( strcmp ( str, "begin nodes" ) != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_nodes(): Fatal error!\n" ); fprintf ( stderr, " No 'begin nodes' in input.\n" ); return NULL; } while ( ( str = fetch_line ( buf, BUFLEN, stream, lineno ) ) != NULL ) { if ( strcmp ( str, "end nodes" ) == 0 ) { return nodes_list; } /* Try to read another node. */ if ( ( node = process_node_line ( str ) ) == NULL ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "get_nodes(): Fatal error!\n" ); fprintf ( stderr, " Bad input on line %d.\n", *lineno ); free_nodes_list ( nodes_list ); return NULL; } /* Add node to node list. */ nodes_list = ll_push ( nodes_list, node ); } /* An error if we reached the end of input without an "end nodes" line. */ fprintf ( stderr, "\n" ); fprintf ( stderr, "get_nodes(): Fatal error!\n" ); fprintf ( stderr, " No 'end nodes' in input.\n" ); free_nodes_list ( nodes_list ); return NULL; } /******************************************************************************/ struct link *make_link ( int n, int n1, int n2, double A, double E, conscell *nodes_list ) /******************************************************************************/ /* Purpose: make_link() allocates memory and assigns data for a link. Licensing: This code is distributed under the MIT license. Modified: 26 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { double L; struct link *link = xmalloc ( sizeof ( *link ) ); double X1; double X2; double Y1; double Y2; for ( conscell *p = nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; if ( node->n == n1 ) { link->np1 = node; X1 = node->X; Y1 = node->Y; } if ( node->n == n2 ) { link->np2 = node; X2 = node->X; Y2 = node->Y; } } L = sqrt ( pow ( X1 - X2, 2 ) + pow ( Y1 - Y2, 2 ) ); link->n = n; link->L = L; link->A = A; link->E = E; link->stress = 0.0; return link; } /******************************************************************************/ struct node *make_node ( int n, double x, double y, int xfixed, int yfixed ) /******************************************************************************/ /* Purpose: make_node() allocates memory and assigns data for a node. Licensing: This code is distributed under the MIT license. Modified: 16 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { struct node *node = xmalloc ( sizeof ( *node ) ); node->n = n; node->X = x; node->Y = y; node->x = x; node->y = y; node->xfixed = xfixed; node->yfixed = yfixed; node->fx = 0.0; node->fy = 0.0; node->rx = 0.0; node->ry = 0.0; return node; } /******************************************************************************/ struct link *process_link_line ( char *str, conscell *nodes_list ) /******************************************************************************/ /* Purpose: process_link_line() reads a link record from a truss definition file. Licensing: This code is distributed under the MIT license. Modified: 17 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { double A; double E; int n; int n1; int n2; if ( sscanf ( str, "link %d: %d %d %lf %lf", &n, &n1, &n2, &A, &E ) == 5 ) { return make_link ( n, n1, n2, A, E, nodes_list ); } else { return NULL; } } /******************************************************************************/ int process_load_line ( char *str, conscell *nodes_list ) /******************************************************************************/ /* Purpose: process_load_line() reads a load record from a truss definition file. Licensing: This code is distributed under the MIT license. Modified: 17 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { double fx; double fy; int n; struct node *node; conscell *p; if ( sscanf ( str, "load %d: %lf %lf", &n, &fx, &fy ) == 3 ) { for ( p = nodes_list; p != NULL; p = p->next ) { node = p->data; if ( node->n == n ) { break; } } if ( p == NULL ) { return 0; } node->fx = fx; node->fy = fy; return 1; } else { return 0; } } /******************************************************************************/ struct node *process_node_line ( char *str ) /******************************************************************************/ /* Purpose: process_node_line() reads a node record from a truss definition file. Licensing: This code is distributed under the MIT license. Modified: 17 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { int n; double x; double y; /* A star before the x or y component indicates that that node is fixed. */ if ( sscanf ( str, "node %d: %lf %lf", &n, &x, &y ) == 3 ) { return make_node ( n, x, y, 0, 0 ); } else if ( sscanf ( str, "node %d: *%lf %lf", &n, &x, &y ) == 3 ) { return make_node ( n, x, y, 1, 0 ); } else if ( sscanf ( str, "node %d: %lf *%lf", &n, &x, &y ) == 3 ) { return make_node ( n, x, y, 0, 1 ); } else if ( sscanf ( str, "node %d: *%lf *%lf", &n, &x, &y ) == 3 ) { return make_node ( n, x, y, 1, 1 ); } else { return NULL; } } /******************************************************************************/ struct truss *read_truss ( FILE *stream ) /******************************************************************************/ /* Purpose: read_truss() reads a file that defines a truss structure. Licensing: This code is distributed under the MIT license. Modified: 16 May 2024 Author: Original C version by Rouben Rostamian. This version by John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { struct truss *truss; conscell *nodes_list; conscell *links_list; int lineno = 0; if ( ( nodes_list = get_nodes ( stream, &lineno ) ) == NULL ) { return NULL; } if ( ( links_list = get_links ( stream, &lineno, nodes_list ) ) == NULL ) { free_nodes_list ( nodes_list ); return NULL; } if ( ! get_loads ( stream, &lineno, nodes_list ) ) { free_nodes_list ( nodes_list ); free_links_list ( links_list ); return NULL; } nodes_list = ll_reverse ( nodes_list ); links_list = ll_reverse ( links_list ); truss = xmalloc ( sizeof *truss ); truss->nodes_list = nodes_list; truss->links_list = links_list; truss->nnodes = ll_length ( nodes_list ); truss->nlinks = ll_length ( links_list ); printf ( "\n" ); printf ( "read_truss():\n" ); printf ( " Read %d nodes, %d links\n", truss->nnodes, truss->nlinks ); return truss; } /******************************************************************************/ void write_truss ( struct truss *truss, char *filename ) /******************************************************************************/ /* Purpose: write_truss() writes a truss structure definition to a file. Licensing: This code is distributed under the MIT license. Modified: 26 May 2024 Author: John Burkardt. Reference: Rouben Rostamian, Programming Projects in C for Students of Engineering, Science, and Mathematics, SIAM, 2014, ISBN: 978-1-611973-49-5 */ { FILE *output; conscell *p; output = fopen ( filename, "wt" ); fprintf ( output, "# truss definition file \n" ); /* Nodes: */ fprintf ( output, "\n" ); fprintf ( output, "# node n: x y\n" ); fprintf ( output, "begin nodes\n" ); for ( p = truss->nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; fprintf ( output, "node %d:", node->n ); if ( node->xfixed ) { fprintf ( output, " *" ); } fprintf ( output, " %g", node->x ); if ( node->yfixed ) { fprintf ( output, " *" ); } fprintf ( output, " %g\n", node->y ); } fprintf ( output, "end nodes\n" ); /* Links */ fprintf ( output, "\n" ); fprintf ( output, "# link n: n1 n2 A E\n" ); fprintf ( output, "begin links\n" ); for ( p = truss->links_list; p != NULL; p = p->next ) { struct link *link = p->data; fprintf ( output, "link %d: %d %d %g %g\n", link->n, link->np1->n, link->np2->n, link->A, link->E ); } fprintf ( output, "end links\n" ); /* Loads */ fprintf ( output, "\n" ); fprintf ( output, "# load nn: fx fy\n" ); fprintf ( output, "begin loads\n" ); for ( p = truss->nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; if ( node->fx != 0.0 || node ->fy != 0.0 ) { fprintf ( output, "load %d: %g %g\n", node->n, node->fx, node->fy ); }; } fprintf ( output, "end loads\n" ); /* Reactions */ fprintf ( output, "\n" ); fprintf ( output, "# node n: rx ry\n" ); fprintf ( output, "begin reactions\n" ); for ( p = truss->nodes_list; p != NULL; p = p->next ) { struct node *node = p->data; if ( node->rx != 0.0 || node ->ry != 0.0 ) { fprintf ( output, "load %d: %g %g\n", node->n, node->rx, node->ry ); }; } fprintf ( output, "end reactions\n" ); /* Stresses */ fprintf ( output, "\n" ); fprintf ( output, "# link n: stress\n" ); fprintf ( output, "begin stresses\n" ); for ( p = truss->links_list; p != NULL; p = p->next ) { struct link *link = p->data; fprintf ( output, "stress %d: %g\n", link->n, link->stress ); } fprintf ( output, "end stresses\n" ); fclose ( output ); return; }