/*******************************************************************************************\ ####### ##### ###### ##### ###### ##### ##### ###### ###### # # # # # # # # # # # # # # # # # ## ## # # # # # # # # # # # # # # # # # # ##### # # ##### ###### # # # # ##### ##### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ##### ###### ####### # ##### ##### # ###### # # Converter from T3d to POOFEM Copyright: Daniel Rypl 1998 - 2014 Czech Technical University in Prague, Faculty of Civil Engineering, Department of Mechanics, Thakurova 7, 166 29 Prague, Czech Republic, email: drypl@fsv.cvut.cz \*******************************************************************************************/ #include #include #include #include #define VERSION "2.0" //#define METIS //#define ELIXIR //#define DEBUG #define MASTER_SLAVE /* if MASTER_SLAVE is defined, master nodes are added as shared to all partitions on which are their slaves; otherwise master nodes are added to all partitions; using MASTER_SLAVE should prevent potential solution failure if some sort of diagonal based local preconditioning is used (in which case on partitions where is no slave there will be zero diagonal entries); however this does not solve the problem if only some of the dofs of the master node are used on given partition while others are not used !!! I have no idea how nested master-slave relationship will behave ! */ /* if the number of partitions is larger than the number of available layers all partitions are drawn in layer 0 */ /* note: quadratic elements are not handled; special care must be taken with respect to quadratic interface elements !!! */ /* isolated nodes are explicitly handled only in node cut; they are output to all partitions always numbered from 1; if number of partitions is 1 and renumbering is not required the numbering of nodes is dependent on their numbering in the input; in element cut isolated nodes are assigned to partitions by Metis */ #ifdef DEBUG #define OUTPUT_REMOTE_PARTITIONS /* output remote partitions for shared remote nodes (normally Null is printed) */ #endif #ifdef METIS #include "metis.h" #undef ASSERT #endif #ifdef ELIXIR #define nodes Ckit_nodes #include "Esimple.h" #undef nodes #undef head #undef list_rec #undef NO #undef YES #undef reverse_list //#define DRAW_NODE_NUMBERS #define MORE_COLORS #ifdef MORE_COLORS #define NUM_COLORS 18 #else #define NUM_COLORS 9 #endif #endif #define FILE_NAME_SIZE 128 #define BUFFER_SIZE 65536 #define KEY_SIZE 32 #define SEPARATOR " \n" #define REMARK '#' #define VERTEX_ENTITY 1 #define CURVE_ENTITY 2 #define SURFACE_ENTITY 3 #define REGION_ENTITY 4 #define PATCH_ENTITY 5 #define SHELL_ENTITY 6 #define INTERFACE_ENTITY 7 #define LINEAR 1 #define QUADRATIC 2 #define TRI_TETRA 3 #define QUAD_HEXA 4 #define EDGE_ELEM 1 #define FACE_ELEM 2 #define QUAD_ELEM 3 #define TETRA_ELEM 4 #define PYRAM_ELEM 5 #define WEDGE_ELEM 6 #define HEXA_ELEM 7 #define NONE_RENUM 0 #define NODE_RENUM 1 #define ELEM_RENUM 2 #define GENERAL_ERROR 1 #define LONG_NAME_ERROR 2 #define FILE_OPEN_ERROR 3 #define FILE_READ_ERROR 4 #define FILE_WRITE_ERROR 5 #define MEMORY_ERROR 6 #define RENUMBER_ERROR 7 typedef enum logic{ NO = 0, YES = 1 }logic; typedef enum prop_key{ NODE_PROP_KEY = 0, ELEM_PROP_KEY = 1, BOUNDARYLOAD_PROP_KEY = 2, BOUNDARYCODE_PROP_KEY = 3, PROP_KEY_NUM }prop_key; typedef struct list_rec list_rec; struct list_rec{ void *item; list_rec *next; }; typedef struct entity_rec entity_rec; struct entity_rec{ long id; int type; long property_id; logic selected; char *elem_type; char *edge_type; char *face_type; char *quad_type; char *tetra_type; char *pyram_type; char *wedge_type; char *hexa_type; list_rec *props[PROP_KEY_NUM]; long nodes, elems; long edges; long faces; long quads; long tetras; long pyrams; long wedges; long hexas; long first_node; long first_edge; long first_face; long first_quad; long first_tetra; long first_hexa; long first_pyram; long first_wedge; int elem_weight; int edge_weight; int face_weight; int quad_weight; int tetra_weight; int pyram_weight; int wedge_weight; int hexa_weight; double width; int partition_id; logic boundary; logic output; entity_rec *ngb_ent[2]; list_rec *masters; }; typedef struct node_rec node_rec; struct node_rec{ long id; /* in: old id out: new id */ long pos; /* out: position of new id equal to old id */ long contact; long *connection; }; typedef struct master_rec master_rec; struct master_rec{ long id; /* assuming that there is not much masters and that the numbers of partitions is reasonable it seems more efficeint to store the whole array of partitions instead of a list_rec */ logic *partitions; }; typedef struct fe_node fe_node; typedef struct fe_edge fe_edge; typedef struct fe_face fe_face; typedef struct fe_quad fe_quad; typedef struct fe_tetra fe_tetra; typedef struct fe_pyram fe_pyram; typedef struct fe_wedge fe_wedge; typedef struct fe_hexa fe_hexa; struct fe_node{ long id, glob_id; entity_rec *entity; double x, y, z; logic master; }; struct fe_edge{ entity_rec *entity; fe_node *node[2]; /* fe_node *nd[1]; */ }; struct fe_face{ entity_rec *entity; fe_node *node[3]; /* fe_node *nd[3]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[3]; }; struct fe_quad{ entity_rec *entity; fe_node *node[4]; /* fe_node *nd[4]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[4]; }; struct fe_tetra{ entity_rec *entity; fe_node *node[4]; /* fe_node *nd[4]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[4]; }; struct fe_pyram{ entity_rec *entity; fe_node *node[5]; /* fe_node *nd[8]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[5]; }; struct fe_wedge{ entity_rec *entity; fe_node *node[6]; /* fe_node *nd[9]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[5]; }; struct fe_hexa{ entity_rec *entity; fe_node *node[8]; /* fe_node *nd[12]; */ short bflag; union{ long ngb_elem_id; /* not used */ entity_rec *bound_ent; }data[6]; }; #define EDGES (edges) #define FACES (edges + faces) #define QUADS (edges + faces + quads) #define TETRAS (edges + faces + quads + tetras) #define PYRAMS (edges + faces + quads + tetras + pyrams) #define WEDGES (edges + faces + quads + tetras + pyrams + wedges) #define HEXAS (edges + faces + quads + tetras + pyrams + wedges + hexas) #define elem_type(ID) (((ID) <= EDGES) ? EDGE_ELEM : \ ((ID) <= FACES) ? FACE_ELEM : \ ((ID) <= QUADS) ? QUAD_ELEM : \ ((ID) <= TETRAS) ? TETRA_ELEM : \ ((ID) <= PYRAMS) ? PYRAM_ELEM : \ ((ID) <= WEDGES) ? WEDGE_ELEM : \ ((ID) <= HEXAS) ? HEXA_ELEM : 0) #define is_edge(ID) ((elem_type(ID) == EDGE_ELEM) ? YES : NO) #define is_face(ID) ((elem_type(ID) == FACE_ELEM) ? YES : NO) #define is_quad(ID) ((elem_type(ID) == QUAD_ELEM) ? YES : NO) #define is_tetra(ID) ((elem_type(ID) == TETRA_ELEM) ? YES : NO) #define is_pyram(ID) ((elem_type(ID) == PYRAM_ELEM) ? YES : NO) #define is_wedge(ID) ((elem_type(ID) == WEDGE_ELEM) ? YES : NO) #define is_hexa(ID) ((elem_type(ID) == HEXA_ELEM) ? YES : NO) /* #define is_edge(ID) (((ID) <= EDGES && (ID)> 0) ? YES : NO) #define is_face(ID) (((ID) <= FACES && (ID)> EDGES) ? YES : NO) #define is_quad(ID) (((ID) <= QUADS && (ID)> FACES) ? YES : NO) #define is_tetra(ID) (((ID) <= TETRAS && (ID)> QUADS) ? YES : NO) #define is_tetra(ID) (((ID) <= PYRAMS && (ID)> TETRAS) ? YES : NO) #define is_tetra(ID) (((ID) <= WEDGES && (ID)> PYRAMS) ? YES : NO) #define is_hexa(ID) (((ID) <= HEXAS && (ID)> WEDGES) ? YES : NO) */ #define global_edge_id(ID) ((ID)) #define global_face_id(ID) ((ID) + EDGES) #define global_quad_id(ID) ((ID) + FACES) #define global_tetra_id(ID) ((ID) + QUADS) #define global_pyram_id(ID) ((ID) + TETRAS) #define global_wedge_id(ID) ((ID) + PYRAMS) #define global_hexa_id(ID) ((ID) + WEDGES) #define local_edge_id(ID) ((ID)) #define local_face_id(ID) ((ID) - EDGES) #define local_quad_id(ID) ((ID) - FACES) #define local_tetra_id(ID) ((ID) - QUADS) #define local_pyram_id(ID) ((ID) - TETRAS) #define local_wedge_id(ID) ((ID) - PYRAMS) #define local_hexa_id(ID) ((ID) - WEDGES) /* note: ordering of neighbouring elements and boundary entities is the same as the one of t3d on output */ static short face_ed_nd[3][2] = {{0, 1}, {1, 2}, {2, 0}}; static short quad_ed_nd[4][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}}; static short tetra_fc_nd[4][3] = {{0, 1, 2}, {0, 3, 1}, {1, 3, 2}, {2, 3, 0}}; static short pyram_fc_nd[5][4] = {{0, 1, 2, 3}, {0, 4, 1, -1}, {1, 4, 2, -1}, {2, 4, 3, -1}, {3, 4, 0, -1}}; static short wedge_fc_nd[5][4] = {{0, 1, 2, -1}, {3, 5, 4, -1}, {0, 3, 4, 1}, {1, 4, 5, 2}, {2, 5, 3, 0}}; static short hexa_fc_nd[6][4] = {{0, 1, 2, 3}, {7, 6, 5, 4}, {1, 0, 4, 5}, {2, 1, 5, 6}, {3, 2, 6, 7}, {0, 3, 7, 4}}; static list_rec *vertex_list = NULL; static list_rec *curve_list = NULL; static list_rec *surface_list = NULL; static list_rec *patch_list = NULL; static list_rec *shell_list = NULL; static list_rec *region_list = NULL; static list_rec *interface_list = NULL; static list_rec *string_list = NULL; static list_rec *id_list = NULL; static list_rec *master_list = NULL; static logic vertex_select = NO; static logic curve_select = NO; static logic surface_select = NO; static logic patch_select = NO; static logic shell_select = NO; static logic region_select = NO; static logic interface_select = NO; static logic entity_select = NO; static logic property_select = NO; static logic specification = NO; static enum keyword{ CANCEL, VERTEX, CURVE, SURFACE, PATCH, SHELL, REGION, INTERFACE, PROPERTY, ALL, EXCEPT, MASTERSLAVE, /* without use */ MASTER, NODEPROP, ELEMPROP, ELEMTYPE, EDGETYPE, TRIATYPE, QUADTYPE, TETRATYPE, HEXATYPE, BLOAD, BOUNDARYLOAD, /* same as bload */ BCODE, BOUNDARYCODE, /* same as bcode */ ELEMWEIGHT, EDGEWEIGHT, TRIAWEIGHT, QUADWEIGHT, TETRAWEIGHT, PYRAMWEIGHT, WEDGEWEIGHT, HEXAWEIGHT, WIDTH, /* non-zero width ensures at least one layer of remote elements */ PARTITION, KEY_NUM }key, last_key = KEY_NUM; static char keyword[KEY_NUM][KEY_SIZE] = { "CANCEL", "VERTEX", "CURVE", "SURFACE", "PATCH", "SHELL", "REGION", "INTERFACE", "PROPERTY", "ALL", "EXCEPT", "MASTERSLAVE", "MASTER", "NODEPROP", "ELEMPROP", "ELEMTYPE", "EDGETYPE", "TRIATYPE", "QUADTYPE", "TETRATYPE", "HEXATYPE", "BLOAD", "BOUNDARYLOAD", "BCODE", "BOUNDARYCODE", "ELEMWEIGHT", "EDGEWEIGHT", "TRIAWEIGHT", "QUADWEIGHT", "TETRAWEIGHT", "PYRAMWEIGHT", "WEDGEWEIGHT", "HEXAWEIGHT", "WIDTH", "PARTITION" }; typedef enum key_case{ MIXED_CASE, UPPER_CASE, LOWER_CASE }key_case; #define KEY_CASE UPPER_CASE static char line_buffer[BUFFER_SIZE], temp_buffer[BUFFER_SIZE]; static char in_err_msg[256], out_err_msg[256]; static FILE *active_in_file = NULL, *active_out_file = NULL; static node_rec *nd_array = NULL; static fe_node *node_array = NULL; static fe_edge *edge_array = NULL; static fe_face *face_array = NULL; static fe_quad *quad_array = NULL; static fe_tetra *tetra_array = NULL; static fe_pyram *pyram_array = NULL; static fe_wedge *wedge_array = NULL; static fe_hexa *hexa_array = NULL; static long nodes = 0, elems = 0, edges = 0, faces = 0, quads = 0, tetras = 0, hexas = 0, pyrams = 0, wedges = 0; static long num_nodes, num_elems; static long *node_num_elems = NULL, *node_con_elems = NULL; static int *remote_node = NULL; static int *remote_elem = NULL; static logic node_cut = NO, elem_cut = NO, renum = NO, master_spec = NO; static logic local_num = NO, global_num = NO; static int nparts = 1; static long *nd_num_nodes = NULL, *nd_con_nodes = NULL, *nd_con_nds = NULL; static long *part_elems = NULL; static double *part_volume = NULL; #ifdef METIS /* the following must be separate arrays because they are passed to metis */ static idxtype *node_num_nodes = NULL, *node_con_nodes = NULL; static idxtype *elem_num_elems = NULL, *elem_con_elems = NULL; static idxtype *node_part = NULL; static idxtype *elem_part = NULL; static idxtype *weight_node = NULL; static idxtype *weight_elem = NULL; #endif static list_rec * add_item_to_list_head(list_rec *any_list, void *item); static list_rec * deep_destroy_list(list_rec *any_list); static list_rec * destroy_list(list_rec *any_list); static list_rec * reverse_list(list_rec *any_list); static long get_list_size(list_rec *any_list); static char * get_next_record(char *err_msg); static char * get_next_relevant_record(char *err_msg); static char * get_first_token(char *buffer); static char * get_next_first_token(char *err_msg); static char * get_next_token(char *err_msg); static int get_token_key(char *token, char keyword[1][KEY_SIZE], int keynum); long get_next_int(char *err_msg); double get_next_fpn(char *err_msg); long get_int_from_token(char *token); double get_fpn_from_token(char *token); static void write_current_record(char *err_msg); static void read_write_next_record(char *in_err_msg, char *out_err_msg); static void read_write_next_relevant_record(char *in_err_msg, char *out_err_msg); static void read_write_unrelevant_records(char *in_err_msg, char *out_err_msg); static void read_write_until_next_relevant_record(char *in_err_msg, char *out_err_msg); static long * get_id(list_rec *id_list, long id); static long * create_id(long id); static master_rec * get_master_id(list_rec *master_list, long id); static master_rec * create_master_id(long id); static entity_rec * get_entity_id(list_rec *entity_list, long id); static entity_rec * create_entity_id(long id); static entity_rec * create_missing_entity_id(long id, int entity_type); static void process_entity_list(void); static void process_property_list(void); static void process_entity_pair_list(void); static void deselect_entity_list(list_rec *entity_list); static void reverse_entity_prop_list(list_rec *entity_list); static void apply_properties(void *item, prop_key prop_key); static void apply_properties_entity_list(list_rec *entity_list, void *item, prop_key prop_key); static void apply_elem_type(char *elem_type); static void apply_elem_type_entity_list(list_rec *entity_list, char *elem_type, char *entity_name); static void apply_width(double width); static void apply_width_entity_list(list_rec *entity_list, double width); static void apply_weight(int weight); static void apply_weight_entity_list(list_rec *entity_list, int weight, char *entity_name); static void apply_partition(int part_id); static void apply_partition_entity_list(list_rec *entity_list, int part_id, char *entity_name); static void apply_master(int master_id); static void apply_master_entity_list(list_rec *entity_list, int master_id, char *entity_name); static void destroy_entity_list(list_rec *entity_list); static void destroy_master_list(list_rec *master_list); static char * store_string(char *string); static void exit_error_message(char *message, int exit_code, int line); #define error_message(MSG, CODE) exit_error_message(MSG, CODE, __LINE__) static void mark_remote_elems(fe_node *node, long node_id, int part_id, long property_id, double width); static void mark_remote_elem(long elem_id, int part_id); static void unmark_nodes(long node_id, int part_id, long property_id); static double calculate_distance_square(fe_node *node1, fe_node *node2); static double calculate_tetra_volume(fe_tetra *tetra); #ifdef ELIXIR void EVFastRedraw(EView *view); /* not declared in any Elixir header file */ #define FONT "-adobe-courier-bold-r-normal--*-120-*-*-m-*-iso8859-1" #define SHRINK 0.9 #define MSIZE 6 static ERenderingType render_mode = NORMAL_RENDERING; static EShadingType shade_mode = CONST_SHADING_RENDERING; static double shrink = 1.0; /* or SHRINK */ static int msize = 0; /* or MSIZE */ static logic *layers = NULL, single_layer = NO; static Widget set_button[NUM_COLORS], add_button[NUM_COLORS], del_button[NUM_COLORS]; static Font font; static void draw_node(fe_node *node, int layer, EPixel color, int type, int msize); static void draw_edge(fe_edge *edge, int layer, EPixel color); static void draw_face(fe_face *face, int layer, EPixel color, EPixel edge_color); static void draw_quad(fe_quad *quad, int layer, EPixel color, EPixel edge_color); static void draw_tetra(fe_tetra *tetra, int layer, EPixel color, EPixel edge_color); static void draw_pyram(fe_pyram *pyram, int layer, EPixel color, EPixel edge_color); static void draw_wedge(fe_wedge *wedge, int layer, EPixel color, EPixel edge_color); static void draw_hexa(fe_hexa *hexa, int layer, EPixel color, EPixel edge_color); static void draw_number(double x, double y, double z, int layer, EPixel color, Font font, long number, char *prefix); static void new_view(Widget w, XtPointer ptr, XtPointer call_data); static void redraw_view(Widget w, XtPointer client_data, XtPointer call_data); static void render_view(Widget w, XtPointer ptr, XtPointer call_data); static void all_domains(Widget w, XtPointer ptr, XtPointer call_data); static void set_domain(Widget w, XtPointer ptr, XtPointer call_data); static void add_domain(Widget w, XtPointer ptr, XtPointer call_data); static void del_domain(Widget w, XtPointer ptr, XtPointer call_data); static void set_nth_domain(Widget w, XtPointer ptr, XtPointer call_data); static void add_nth_domain(Widget w, XtPointer ptr, XtPointer call_data); static void del_nth_domain(Widget w, XtPointer ptr, XtPointer call_data); static int view_all_domains(NODE data, NODE v); static int view_set_domain(NODE data, NODE v); static int view_add_domain(NODE data, NODE v); static int view_del_domain(NODE data, NODE v); static void toggle_shrink(Widget w, XtPointer ptr, XtPointer call_data); static int shrink_graphics(NODE data, NODE gr_obj); static void toggle_msize(Widget w, XtPointer ptr, XtPointer call_data); static int msize_graphics(NODE data, NODE gr_obj); static int view_normalize_off(NODE data, NODE v); static int view_normalize_on(NODE data, NODE v); static void fit_all(Widget w, XtPointer cmdtext_ptr, XtPointer call_data); static void view_origin(Widget w, XtPointer cmdtext_ptr, XtPointer call_data); #endif int renumber_mesh(long num_nodes, node_rec *node_array, long num_shift, double *old_profile, double *new_profile); int main(int argc, char **argv) { long node_id, elem_id, entity_id, property_id, last_entity_id = 0; long node, elem, nd, node1, node2, node3, node4, elem1, elem2, nd_id[8]; long i, j, k, m, n, p, j1, j2, j3, j4, size, pos, number, con_node, ii, *ident = NULL; long curve_id[4], curve_prop[4], bound_ent_id[6], bound_ent_prop[6], load_id, code_id, master_id, isolated = 0; long part_edges, part_faces, part_quads, part_tetras, part_pyrams, part_wedges, part_hexas; int mesh_type, elem_degree, renum_type, output_type, entity_type, last_entity_type = 0, bound_ent_tp[6]; int records, recs, add_recs = 0, count, part, part_id, status, contact, length; int options[5], edge_cut, graph_size, num_flag, weight_flag = 0, type, num, weight; int csect, mater, bcond, nic, timef, barriers = 0, randgens = 0; double x, y, z, width, old_profile, new_profile, volume, max_volume; logic bflag, *part_flag = NULL, shared, remote, bnd_prop; logic domain = NO, interface_last = NO, static_dd = NO, min_first = NO, help = NO, parts = NO; logic obligatory = NO, optional = NO; logic csect_spec = NO, mater_spec = NO, bcond_spec = NO, nic_spec = NO, timef_spec = NO; logic barriers_spec = NO, randgens_spec = NO, topology_spec = NO; FILE *control_file = NULL, *t3d_out_file = NULL; FILE *poofem_in_file = NULL, *poofem_domain_file = NULL; FILE *oofem_in_file = NULL, *oofem_domain_file = NULL; char control_name[FILE_NAME_SIZE], t3d_out_name[FILE_NAME_SIZE]; char oofem_in_name[FILE_NAME_SIZE], oofem_domain_name[FILE_NAME_SIZE + 7]; char poofem_in_name[FILE_NAME_SIZE + 5], poofem_domain_name[FILE_NAME_SIZE + 12]; char *token = NULL, *string = NULL, err_msg[256], topology[128]; char oofem_out_name[FILE_NAME_SIZE], suffix[5], *elem_type = NULL; list_rec *entity_list = NULL, *prop_list = NULL; entity_rec *entity = NULL, *ent = NULL, *iface_ent = NULL; fe_node *fe_node = NULL, *fe_nd = NULL; fe_edge *fe_edge = NULL; fe_face *fe_face = NULL; fe_quad *fe_quad = NULL; fe_tetra *fe_tetra = NULL; fe_pyram *fe_pyram = NULL; fe_wedge *fe_wedge = NULL; fe_hexa *fe_hexa = NULL; #ifdef MASTER_SLAVE list_rec *list = NULL; master_rec *master = NULL; #endif #ifdef METIS int min_dd = 2, max_dd = 0; int *dd_number = NULL; long num_renum_nodes; #endif #ifdef ELIXIR EView *view = NULL; EPixel white, black, colors[NUM_COLORS]; EPixel green, red, yellow, magenta, cyan, blue, orange, purple, pink; BOOLEAN success; logic elixir = NO; char app_name[] = "T3d2poofem - Metis - DD", *app_nm = app_name; Arg args[2]; int argn; #endif if(argc == 2){ if(strcmp(*(argv + 1), "-h") == 0)help = YES; } fprintf(stdout, "\n"); fprintf(stdout, "****************************************\n"); fprintf(stdout, "T3d2poofem: Converter from T3d to Poofem\n"); fprintf(stdout, "Copyright: Daniel Rypl, 2014\n"); fprintf(stdout, "Version: %s\n", VERSION); fprintf(stdout, "****************************************\n"); fprintf(stdout, "\n"); if(argc < 4 || help == YES){ #ifdef METIS fprintf(stdout, "Usage: t3d2poofem [-h] control_file t3d_output_file oofem_input_file [options]\n\n"); fprintf(stdout, "Options: -np # number of partitions (default %d)\n", nparts); fprintf(stdout, " -nc node cut (default)\n"); fprintf(stdout, " -ec element cut\n"); fprintf(stdout, " -gn global numbering (default)\n"); fprintf(stdout, " -ln local numbering\n"); fprintf(stdout, " -rn node renumbering (for node cut only and local numbering only)\n"); fprintf(stdout, " -last number interface nodes last (for node cut only)\n"); fprintf(stdout, " -sdd static domain decomposition (for node cut only)\n"); fprintf(stdout, " -din generate also domain input file\n"); /* average element volume is considered (partition volume/number of elems), I have no idea what is this good for */ fprintf(stdout, " -dsz reorder partitions according to average element size\n"); fprintf(stdout, " (for node cut, pure tetra mesh and not sdd only)\n"); #ifdef ELIXIR fprintf(stdout, " -X graphic interface (only for -np #> 1)\n"); #endif #else fprintf(stdout, "Usage: t3d2poofem [-h] control_file t3d_output_file oofem_input_file [options]\n\n"); fprintf(stdout, "Options: -rn node renumbering\n"); fprintf(stdout, " -din generate also domain file\n"); #endif fprintf(stdout, " -h help (list of control file keywords)\n"); fprintf(stdout, "\n"); if(help == YES){ fprintf(stdout, "\n"); fprintf(stdout, "Control file keywords\n"); fprintf(stdout, "=====================\n"); fprintf(stdout, "\n"); fprintf(stdout, "Model entity specification\n"); fprintf(stdout, "--------------------------\n"); fprintf(stdout, "{Vertex | Curve | Surface | Patch | Shell | Region | Interface} {All [Except ] | }\n"); fprintf(stdout, "\n"); fprintf(stdout, "Property specification\n"); fprintf(stdout, "-----------------------\n"); fprintf(stdout, "Property {All [Except ] | }\n"); fprintf(stdout, "\n"); fprintf(stdout, "Model and property specification cancelation\n"); fprintf(stdout, "--------------------------------------------\n"); fprintf(stdout, "Cancel\n"); fprintf(stdout, "\n"); fprintf(stdout, "Feature specification (entity/property related)\n"); fprintf(stdout, "-----------------------------------------------\n"); fprintf(stdout, "{Nodeprop | Elemprop} string\n"); fprintf(stdout, "{Edgetype | Triatype | Quadtype | Tetratype | Hexatype} string\n"); fprintf(stdout, "{Bload | Boundaryload | Bcode | Boundarycode} int\n"); fprintf(stdout, "{Edgeweight | Triaweight | Quadweight} int\n"); fprintf(stdout, "{Tetraweight | Pyramweight | Wedgeweight | Hexaweight} int\n"); fprintf(stdout, "{Width fpn}\n"); fprintf(stdout, "{Partition int}\n"); fprintf(stdout, "\n"); fprintf(stdout, "Master specification (entity related)\n"); fprintf(stdout, "-------------------------------------\n"); fprintf(stdout, "Master \n"); fprintf(stdout, "\n"); exit(0); } exit(1); } if(strlen(argv[1])>= FILE_NAME_SIZE)error_message("Too long control_file name", LONG_NAME_ERROR); if(strlen(argv[2])>= FILE_NAME_SIZE)error_message("Too long t3d_output_file name", LONG_NAME_ERROR); if(strlen(argv[3])>= FILE_NAME_SIZE)error_message("Too long oofem_input_file name", LONG_NAME_ERROR); strncpy(control_name, argv[1], FILE_NAME_SIZE); strncpy(t3d_out_name, argv[2], FILE_NAME_SIZE); strncpy(oofem_in_name, argv[3], FILE_NAME_SIZE); argc -= 4; argv += 4; while(argc--){ #ifdef METIS if(strcmp(*argv, "-np") == 0){ nparts = atoi(*++argv); if(nparts <= 0)error_message("Invalid number of partitions", GENERAL_ERROR); argc--; argv++; parts = YES; continue; } if(strcmp(*argv, "-nc") == 0){ if(elem_cut == YES)error_message("Ambiguous cut specification", GENERAL_ERROR); node_cut = YES; argv++; continue; } if(strcmp(*argv, "-ec") == 0){ if(node_cut == YES)error_message("Ambiguous cut specification", GENERAL_ERROR); fprintf(stderr, "WARNING: Element-cut output keywords may not consistent with OOFEM\n"); elem_cut = YES; argv++; continue; } if(strcmp(*argv, "-gn") == 0){ if(local_num == YES)error_message("Ambiguous numbering specification", GENERAL_ERROR); global_num = YES; argv++; continue; } if(strcmp(*argv, "-ln") == 0){ if(global_num == YES)error_message("Ambiguous numbering specification", GENERAL_ERROR); local_num = YES; argv++; continue; } if(strcmp(*argv, "-last") == 0){ interface_last = YES; argv++; continue; } if(strcmp(*argv, "-sdd") == 0){ static_dd = YES; argv++; continue; } if(strcmp(*argv, "-dsz") == 0){ min_first = YES; argv++; continue; } #ifdef ELIXIR if(strcmp(*argv, "-X") == 0){ elixir = YES; argv++; continue; } #endif #endif if(strcmp(*argv, "-rn") == 0){ renum = YES; argv++; continue; } if(strcmp(*argv, "-din") == 0){ domain = YES; argv++; continue; } if(strcmp(*argv, "-h") == 0){ argv++; continue; } fprintf(stderr, "Unknown option: %s\n", *argv); } if(parts == NO){ fprintf(stderr, "WARNING: Single partition assumed.\n"); #ifdef ELIXIR if(elixir == YES){ fprintf(stderr, " Graphic interface not started.\n"); elixir = NO; } #endif } #ifdef METIS if(node_cut == NO && elem_cut == NO)node_cut = YES; if(global_num == NO && local_num == NO)global_num = YES; if(renum == YES && global_num == YES){ fprintf(stderr, "WARNING: Renumbering ignored for global numbering.\n"); renum = NO; } if(static_dd == YES && elem_cut == YES){ fprintf(stderr, "WARNING: Static partitioning ignored for element cut.\n"); static_dd = NO; } if(interface_last == YES && elem_cut == YES){ fprintf(stderr, "WARNING: Numbering interface nodes last ignored for element cut.\n"); interface_last = NO; } #endif if((control_file = fopen(control_name, "r")) == NULL){ sprintf(err_msg, "File %s opening error", control_name); error_message(err_msg, FILE_OPEN_ERROR); } if((t3d_out_file = fopen(t3d_out_name, "r")) == NULL){ sprintf(err_msg, "File %s opening error", t3d_out_name); error_message(err_msg, FILE_OPEN_ERROR); } active_in_file = t3d_out_file; sprintf(in_err_msg, "File %s reading error", t3d_out_name); get_next_relevant_record(in_err_msg); if(sscanf(line_buffer, "%d %d %d %d", &mesh_type, &elem_degree, &renum_type, &output_type) != 4) error_message(in_err_msg, FILE_READ_ERROR); if((output_type &= 8) == 0) error_message("Invalid t3d -p option (8-missing)", GENERAL_ERROR); if((output_type &= 512) != 0){ fprintf(stderr, "WARNING: Output option 512 not handled.\n"); fprintf(stderr, " Edgeload (if any) applied to 3D elements is ignored\n"); } get_next_relevant_record(in_err_msg); switch(mesh_type){ case TRI_TETRA: if(sscanf(line_buffer, "%ld %ld %ld %ld", &nodes, &edges, &faces, &tetras) != 4) error_message(in_err_msg, FILE_READ_ERROR); elems = edges + faces + tetras; break; case QUAD_HEXA: if(sscanf(line_buffer, "%ld %ld %ld %ld", &nodes, &edges, &quads, &hexas) != 4) error_message(in_err_msg, FILE_READ_ERROR); elems = edges + quads + hexas; break; case TRI_TETRA + QUAD_HEXA: if(sscanf(line_buffer, "%ld %ld %ld %ld %ld %ld %ld %ld", &nodes, &edges, &faces, &quads, &tetras, &pyrams, &wedges, &hexas) != 8) error_message(in_err_msg, FILE_READ_ERROR); elems = edges + faces + quads + tetras + pyrams + wedges + hexas; break; default: error_message("Unknown element type", GENERAL_ERROR); break; } /* if(pyrams != 0 || wedges != 0)error_message("Pyramids and wedges not supported", GENERAL_ERROR); */ #ifdef METIS if(min_first == YES){ if(elems != tetras || elem_cut == YES || static_dd == YES){ fprintf(stderr, "WARNING: Option -dsz ignored\n"); min_first = NO; } } #endif switch(elem_degree){ case LINEAR: break; case QUADRATIC: error_message("Quadratic elements not supported", GENERAL_ERROR); break; default: error_message("Unsupported element degree", GENERAL_ERROR); } switch(renum_type){ case NONE_RENUM: break; case NODE_RENUM: if(renum == YES && nparts == 1 && static_dd == NO){ fprintf(stderr, "WARNING: Renumbered mesh ==> node renumbering ignored.\n"); renum = NO; } break; case ELEM_RENUM: error_message("Renumbering of elements not supported\n", GENERAL_ERROR); break; default: error_message("Unknown renumbering type", GENERAL_ERROR); } if(renum == YES && elem_cut == YES && nparts> 1){ fprintf(stderr, "WARNING: Mesh renumbering not supported for element cut.\n"); renum = NO; } if(nodes == 0) error_message("Not enough nodes found", GENERAL_ERROR); if((node_array = (struct fe_node *)calloc(nodes, sizeof(struct fe_node))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if(edges != 0){ if((edge_array = (struct fe_edge *)calloc(edges, sizeof(struct fe_edge))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(faces != 0){ if((face_array = (struct fe_face *)calloc(faces, sizeof(struct fe_face))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(quads != 0){ if((quad_array = (struct fe_quad *)calloc(quads, sizeof(struct fe_quad))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(tetras != 0){ if((tetra_array = (struct fe_tetra *)calloc(tetras, sizeof(struct fe_tetra))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(pyrams != 0){ if((pyram_array = (struct fe_pyram *)calloc(pyrams, sizeof(struct fe_pyram))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(wedges != 0){ if((wedge_array = (struct fe_wedge *)calloc(wedges, sizeof(struct fe_wedge))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(hexas != 0){ if((hexa_array = (struct fe_hexa *)calloc(hexas, sizeof(struct fe_hexa))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } /* I am using fscanf because I am reading fixed format, any item of which is used as flow control variable; to enable use of variable number of parameters on the input line the rest of the record (at least the new-line character at the end of the record) is read into string from which the remaining variables are read */ for(i = 0; i < nodes; i++){ if(fscanf(active_in_file, "%ld %lf %lf %lf %d %ld %ld", &node_id, &x, &y, &z, &entity_type, &entity_id, &property_id) != 7) error_message(in_err_msg, FILE_READ_ERROR); get_next_record(in_err_msg); switch(entity_type){ case VERTEX_ENTITY: entity_list = vertex_list; break; case CURVE_ENTITY: entity_list = curve_list; /* if(sscanf(line_buffer, "%lf %lf %lf", &tx, &ty, &tz) != 3) error_message(in_err_msg, FILE_READ_ERROR); */ break; case SURFACE_ENTITY: entity_list = surface_list; /* if(sscanf(line_buffer, "%lf %lf %lf", &nx, &ny, &nz) != 3) error_message(in_err_msg, FILE_READ_ERROR); */ break; case PATCH_ENTITY: entity_list = patch_list; /* if(sscanf(line_buffer, "%lf %lf %lf", &nx, &ny, &nz) != 3) error_message(in_err_msg, FILE_READ_ERROR); */ break; case SHELL_ENTITY: entity_list = shell_list; /* if(sscanf(line_buffer, "%lf %lf %lf", &nx, &ny, &nz) != 3) error_message(in_err_msg, FILE_READ_ERROR); */ break; case REGION_ENTITY: entity_list = region_list; break; case INTERFACE_ENTITY: entity_list = interface_list; break; default: error_message("Unknown entity type", GENERAL_ERROR); } if(node_id <= 0 || node_id> nodes) error_message("Incosistent node numbering", GENERAL_ERROR); fe_node = &(node_array[node_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; } if(entity -> first_node == 0)entity -> first_node = node_id; entity -> nodes++; fe_node -> id = fe_node -> glob_id = node_id; fe_node -> entity = entity; fe_node -> x = x; fe_node -> y = y; fe_node -> z = z; fe_node -> master = NO; } iface_ent = create_missing_entity_id(-1, INTERFACE_ENTITY); if(elem_degree == LINEAR){ if(edges != 0){ for(i = 0; i < edges; i++){ get_next_relevant_record(in_err_msg); if(sscanf(line_buffer, "%ld %ld %ld %d %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &entity_type, &entity_id, &property_id) != 6) error_message(in_err_msg, FILE_READ_ERROR); if(is_edge(elem_id) == NO) error_message("Inconsistent edge numbering", GENERAL_ERROR); elem_id = local_edge_id(elem_id); /* macro */ fe_edge = &(edge_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ if(entity_type == CURVE_ENTITY)entity_list = curve_list; if(entity_type == INTERFACE_ENTITY)entity_list = interface_list; entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_edge == 0)entity -> first_edge = elem_id; entity -> edges++; entity -> elems++; fe_edge -> entity = entity; for(j = 0; j < 2; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid edge nodes", GENERAL_ERROR); fe_edge -> node[j] = &(node_array[nd - 1]); } } } if(faces != 0){ for(i = 0; i < faces; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &entity_type, &entity_id, &property_id, &curve_id[0], &curve_id[1], &curve_id[2], &curve_prop[0], &curve_prop[1], &curve_prop[2]); if(num != 10 && num != 13) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 13) ? YES : NO; if(is_face(elem_id) == NO) error_message("Inconsistent face numbering", GENERAL_ERROR); elem_id = local_face_id(elem_id); /* macro */ fe_face = &(face_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ if(entity_type == SURFACE_ENTITY)entity_list = surface_list; if(entity_type == PATCH_ENTITY)entity_list = patch_list; if(entity_type == SHELL_ENTITY)entity_list = shell_list; entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_face == 0)entity -> first_face = elem_id; entity -> faces++; entity -> elems++; fe_face -> entity = entity; for(j = 0; j < 3; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid face nodes", GENERAL_ERROR); fe_face -> node[j] = &(node_array[nd - 1]); fe_face -> data[j].ngb_elem_id = 0; if(curve_id[j] != 0){ if((ent = get_entity_id(curve_list, curve_id[j])) == NULL){ ent = create_missing_entity_id(curve_id[j], CURVE_ENTITY); if(bnd_prop == YES)ent -> property_id = curve_prop[j]; } fe_face -> data[j].bound_ent = ent; fe_face -> bflag |= 1 << j; ent -> boundary = YES; } } } } if(quads != 0){ for(i = 0; i < quads; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &nd_id[3], &entity_type, &entity_id, &property_id, &curve_id[0], &curve_id[1], &curve_id[2], &curve_id[3], &curve_prop[0], &curve_prop[1], &curve_prop[2], &curve_prop[3]); if(num != 12 && num != 16) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 16) ? YES : NO; if(is_quad(elem_id) == NO) error_message("Inconsistent quad numbering", GENERAL_ERROR); elem_id = local_quad_id(elem_id); /* macro */ fe_quad = &(quad_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ if(entity_type == SURFACE_ENTITY)entity_list = surface_list; if(entity_type == PATCH_ENTITY)entity_list = patch_list; if(entity_type == SHELL_ENTITY)entity_list = shell_list; if(entity_type == INTERFACE_ENTITY)entity_list = interface_list; entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_quad == 0)entity -> first_quad = elem_id; entity -> quads++; entity -> elems++; fe_quad -> entity = entity; for(j = 0; j < 4; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid quad nodes", GENERAL_ERROR); fe_quad -> node[j] = &(node_array[nd - 1]); fe_quad -> data[j].ngb_elem_id = 0; if(curve_id[j] != 0){ if(curve_id[j] == -1) ent = iface_ent; else{ if((ent = get_entity_id(curve_list, curve_id[j])) == NULL){ ent = create_missing_entity_id(curve_id[j], CURVE_ENTITY); if(bnd_prop == YES)ent -> property_id = curve_prop[j]; } } fe_quad -> data[j].bound_ent = ent; fe_quad -> bflag |= 1 << j; ent -> boundary = YES; } } } } if(tetras != 0){ for(i = 0; i < tetras; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %d %d %d %d %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &nd_id[3], &entity_type, &entity_id, &property_id, &bound_ent_id[0], &bound_ent_id[1], &bound_ent_id[2], &bound_ent_id[3], &bound_ent_tp[0], &bound_ent_tp[1], &bound_ent_tp[2], &bound_ent_tp[3], &bound_ent_prop[0], &bound_ent_prop[1], &bound_ent_prop[2], &bound_ent_prop[3]); if(num != 16 && num != 20) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 20) ? YES : NO; if(is_tetra(elem_id) == NO) error_message("Inconsistent tetra numbering", GENERAL_ERROR); elem_id = local_tetra_id(elem_id); /* macro */ fe_tetra = &(tetra_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ entity = get_entity_id(region_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_tetra == 0)entity -> first_tetra = elem_id; entity -> tetras++; entity -> elems++; fe_tetra -> entity = entity; for(j = 0; j < 4; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid tetra nodes", GENERAL_ERROR); fe_tetra -> node[j] = &(node_array[nd - 1]); fe_tetra -> data[j].ngb_elem_id = 0; if(bound_ent_id[j] != 0){ if(bound_ent_tp[j] == SURFACE_ENTITY)entity_list = surface_list; if(bound_ent_tp[j] == PATCH_ENTITY)entity_list = patch_list; if(bound_ent_tp[j] == SHELL_ENTITY)entity_list = shell_list; if((ent = get_entity_id(entity_list, bound_ent_id[j])) == NULL){ ent = create_missing_entity_id(bound_ent_id[j], bound_ent_tp[j]); if(bnd_prop == YES)ent -> property_id = bound_ent_prop[j]; } fe_tetra -> data[j].bound_ent = ent; fe_tetra -> bflag |= 1 << j; ent -> boundary = YES; /* I do not need ngb 3D entities for 2D entity without elements; this is used to prevent "Unexpected situation" below when a 2D entity is shared by more than just two 3D entities; this may happen if slave 2D entities bounding a 3D entity are used in t3d model; I also rely on the fact that elements are read in the order of ascending dimension and that the mesh is either linear or quadratic */ if(ent -> first_face == 0 && ent -> first_quad == 0)continue; if(ent -> ngb_ent[0] == NULL) ent -> ngb_ent[0] = entity; else{ if(ent -> ngb_ent[0] != entity){ if(ent -> ngb_ent[1] == NULL) ent -> ngb_ent[1] = entity; else{ if(ent -> ngb_ent[1] != entity) error_message("Unexpected situation", GENERAL_ERROR); } } } } } } } if(pyrams != 0){ for(i = 0; i < pyrams; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %d %d %d %d %d %ld %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &nd_id[3], &nd_id[4], &entity_type, &entity_id, &property_id, &bound_ent_id[0], &bound_ent_id[1], &bound_ent_id[2], &bound_ent_id[3], &bound_ent_id[4], &bound_ent_tp[0], &bound_ent_tp[1], &bound_ent_tp[2], &bound_ent_tp[3], &bound_ent_tp[4], &bound_ent_prop[0], &bound_ent_prop[1], &bound_ent_prop[2], &bound_ent_prop[3], &bound_ent_prop[4]); if(num != 19 && num != 24) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 24) ? YES : NO; if(is_pyram(elem_id) == NO) error_message("Inconsistent pyram numbering", GENERAL_ERROR); elem_id = local_pyram_id(elem_id); /* macro */ fe_pyram = &(pyram_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ entity = get_entity_id(region_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_pyram == 0)entity -> first_pyram = elem_id; entity -> pyrams++; entity -> elems++; fe_pyram -> entity = entity; for(j = 0; j < 5; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid pyram nodes", GENERAL_ERROR); fe_pyram -> node[j] = &(node_array[nd - 1]); fe_pyram -> data[j].ngb_elem_id = 0; if(bound_ent_id[j] != 0){ if(bound_ent_tp[j] == SURFACE_ENTITY)entity_list = surface_list; if(bound_ent_tp[j] == PATCH_ENTITY)entity_list = patch_list; if(bound_ent_tp[j] == SHELL_ENTITY)entity_list = shell_list; if((ent = get_entity_id(entity_list, bound_ent_id[j])) == NULL){ ent = create_missing_entity_id(bound_ent_id[j], bound_ent_tp[j]); if(bnd_prop == YES)ent -> property_id = bound_ent_prop[j]; } fe_pyram -> data[j].bound_ent = ent; fe_pyram -> bflag |= 1 << j; ent -> boundary = YES; /* I do not need ngb 3D entities for 2D entity without elements; this is used to prevent "Unexpected situation" below when a 2D entity is shared by more than just two 3D entities; this may happen if slave 2D entities bounding a 3D entity are used in t3d model; I also rely on the fact that elements are read in the order of ascending dimension and that the mesh is either linear or quadratic */ if(ent -> first_face == 0 && ent -> first_quad == 0)continue; if(ent -> ngb_ent[0] == NULL) ent -> ngb_ent[0] = entity; else{ if(ent -> ngb_ent[0] != entity){ if(ent -> ngb_ent[1] == NULL) ent -> ngb_ent[1] = entity; else{ if(ent -> ngb_ent[1] != entity) error_message("Unexpected situation", GENERAL_ERROR); } } } } } } } if(wedges != 0){ for(i = 0; i < wedges; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %d %d %d %d %d %ld %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &nd_id[3], &nd_id[4], &nd_id[5], &entity_type, &entity_id, &property_id, &bound_ent_id[0], &bound_ent_id[1], &bound_ent_id[2], &bound_ent_id[3], &bound_ent_id[4], &bound_ent_tp[0], &bound_ent_tp[1], &bound_ent_tp[2], &bound_ent_tp[3], &bound_ent_tp[4], &bound_ent_prop[0], &bound_ent_prop[1], &bound_ent_prop[2], &bound_ent_prop[3], &bound_ent_prop[4]); if(num != 20 && num != 25) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 25) ? YES : NO; if(is_wedge(elem_id) == NO) error_message("Inconsistent wedge numbering", GENERAL_ERROR); elem_id = local_wedge_id(elem_id); /* macro */ fe_wedge = &(wedge_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ if(entity_type == REGION_ENTITY)entity_list = region_list; if(entity_type == INTERFACE_ENTITY)entity_list = interface_list; entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_wedge == 0)entity -> first_wedge = elem_id; entity -> wedges++; entity -> elems++; fe_wedge -> entity = entity; for(j = 0; j < 6; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid wedge nodes", GENERAL_ERROR); fe_wedge -> node[j] = &(node_array[nd - 1]); } for(j = 0; j < 5; j++){ fe_wedge -> data[j].ngb_elem_id = 0; if(bound_ent_id[j] != 0){ if(bound_ent_id[j] == -1) ent = iface_ent; else{ if(bound_ent_tp[j] == SURFACE_ENTITY)entity_list = surface_list; if(bound_ent_tp[j] == PATCH_ENTITY)entity_list = patch_list; if(bound_ent_tp[j] == SHELL_ENTITY)entity_list = shell_list; if((ent = get_entity_id(entity_list, bound_ent_id[j])) == NULL){ ent = create_missing_entity_id(bound_ent_id[j], bound_ent_tp[j]); if(bnd_prop == YES)ent -> property_id = bound_ent_prop[j]; } } fe_wedge -> data[j].bound_ent = ent; fe_wedge -> bflag |= 1 << j; ent -> boundary = YES; /* I do not need ngb 3D entities for 2D entity without elements; this is used to prevent "Unexpected situation" below when a 2D entity is shared by more than just two 3D entities; this may happen if slave 2D entities bounding a 3D entity are used in t3d model; I also rely on the fact that elements are read in the order of ascending dimension and that the mesh is either linear or quadratic */ if(ent -> first_face == 0 && ent -> first_quad == 0)continue; if(ent -> ngb_ent[0] == NULL) ent -> ngb_ent[0] = entity; else{ if(ent -> ngb_ent[0] != entity){ if(ent -> ngb_ent[1] == NULL) ent -> ngb_ent[1] = entity; else{ if(ent -> ngb_ent[1] != entity) error_message("Unexpected situation", GENERAL_ERROR); } } } } } } } if(hexas != 0){ for(i = 0; i < hexas; i++){ get_next_relevant_record(in_err_msg); num = sscanf(line_buffer, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %ld %d %d %d %d %d %d %ld %ld %ld %ld %ld %ld", &elem_id, &nd_id[0], &nd_id[1], &nd_id[2], &nd_id[3], &nd_id[4], &nd_id[5], &nd_id[6], &nd_id[7], &entity_type, &entity_id, &property_id, &bound_ent_id[0], &bound_ent_id[1], &bound_ent_id[2], &bound_ent_id[3], &bound_ent_id[4], &bound_ent_id[5], &bound_ent_tp[0], &bound_ent_tp[1], &bound_ent_tp[2], &bound_ent_tp[3], &bound_ent_tp[4], &bound_ent_tp[5], &bound_ent_prop[0], &bound_ent_prop[1], &bound_ent_prop[2], &bound_ent_prop[3], &bound_ent_prop[4], &bound_ent_prop[5]); if(num != 24 && num != 30) error_message(in_err_msg, FILE_READ_ERROR); bnd_prop = (num == 30) ? YES : NO; if(is_hexa(elem_id) == NO) error_message("Inconsistent hexa numbering", GENERAL_ERROR); elem_id = local_hexa_id(elem_id); /* macro */ fe_hexa = &(hexa_array[elem_id - 1]); if(last_entity_type != entity_type || last_entity_id != entity_id){ if(entity_type == REGION_ENTITY)entity_list = region_list; if(entity_type == INTERFACE_ENTITY)entity_list = interface_list; entity = get_entity_id(entity_list, entity_id); if(entity == NULL){ entity = create_missing_entity_id(entity_id, entity_type); entity -> property_id = property_id; } last_entity_type = entity_type; last_entity_id = entity_id; entity -> output = YES; } if(entity -> first_hexa == 0)entity -> first_hexa = elem_id; entity -> hexas++; entity -> elems++; fe_hexa -> entity = entity; for(j = 0; j < 8; j++){ nd = nd_id[j]; if(nd <= 0 || nd> nodes) error_message("Invalid hexa nodes", GENERAL_ERROR); fe_hexa -> node[j] = &(node_array[nd - 1]); } for(j = 0; j < 6; j++){ fe_hexa -> data[j].ngb_elem_id = 0; if(bound_ent_id[j] != 0){ if(bound_ent_id[j] == -1) ent = iface_ent; else{ if(bound_ent_tp[j] == SURFACE_ENTITY)entity_list = surface_list; if(bound_ent_tp[j] == PATCH_ENTITY)entity_list = patch_list; if(bound_ent_tp[j] == SHELL_ENTITY)entity_list = shell_list; if((ent = get_entity_id(entity_list, bound_ent_id[j])) == NULL){ ent = create_missing_entity_id(bound_ent_id[j], bound_ent_tp[j]); if(bnd_prop == YES)ent -> property_id = bound_ent_prop[j]; } } fe_hexa -> data[j].bound_ent = ent; fe_hexa -> bflag |= 1 << j; ent -> boundary = YES; /* I do not need ngb 3D entities for 2D entity without elements; this is used to prevent "Unexpected situation" below when a 2D entity is shared by more than just two 3D entities; this may happen if slave 2D entities bounding a 3D entity are used in t3d model; I also rely on the fact that elements are read in the order of ascending dimension and that the mesh is either linear or quadratic */ if(ent -> first_face == 0 && ent -> first_quad == 0)continue; if(ent -> ngb_ent[0] == NULL) ent -> ngb_ent[0] = entity; else{ if(ent -> ngb_ent[0] != entity){ if(ent -> ngb_ent[1] == NULL) ent -> ngb_ent[1] = entity; else{ if(ent -> ngb_ent[1] != entity) error_message("Unexpected situation", GENERAL_ERROR); } } } } } } } } fclose(t3d_out_file); active_in_file = control_file; sprintf(in_err_msg, "Unexpected end of control file %s", control_name); if(nparts == 1){ /* OOFEM_SEQ start */ if((oofem_in_file = fopen(oofem_in_name, "w")) == NULL){ sprintf(err_msg, "File %s opening error", oofem_in_name); error_message(err_msg, FILE_OPEN_ERROR); } active_out_file = oofem_in_file; sprintf(out_err_msg, "File %s writing error", oofem_in_name); read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM output file record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM problem description record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM analysis type record */ length = (int)strlen(string = line_buffer); for(i = 0; i < length; i++, string++){ if(strncasecmp(string, "nmsteps", 7) == 0){ /* OOFEM metastep count */ string += 7; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "nmodules", 8) == 0){ /* OOFEM export module count */ string += 8; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "ninitmodules", 12) == 0){ /* OOFEM init module count */ string += 12; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "nxfemman", 8) == 0){ /* OOFEM xfem manager count */ string += 8; sscanf(string, "%d", &recs); add_recs += recs; } } for(i = 0; i < add_recs; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM analysis additional records */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM domain record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM output manager record */ read_write_unrelevant_records(in_err_msg, out_err_msg); } /* OOFEM_SEQ end */ #ifdef METIS /* OOFEM_PAR start */ else{ get_next_relevant_record(in_err_msg); /* OOFEM output file record */ if(sscanf(line_buffer, "%s", oofem_out_name) != 1){ sprintf(err_msg, "File %s reading error", control_name); error_message(err_msg, FILE_READ_ERROR); } get_next_relevant_record(in_err_msg); /* OOFEM problem description record */ get_next_relevant_record(in_err_msg); /* OOFEM analysis type record */ length = (int)strlen(string = line_buffer); for(i = 0; i < length; i++, string++){ if(strncasecmp(string, "nmsteps", 7) == 0){ /* OOFEM metastep count */ string += 7; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "nmodules", 8) == 0){ /* OOFEM export module count */ string += 8; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "ninitmodules", 12) == 0){ /* OOFEM init module count */ string += 12; sscanf(string, "%d", &recs); add_recs += recs; } if(strncasecmp(string, "nxfemman", 8) == 0){ /* OOFEM xfem manager count */ string += 8; sscanf(string, "%d", &recs); add_recs += recs; } } for(i = 0; i < add_recs; i++) get_next_relevant_record(in_err_msg); /* OOFEM analysis additional records */ get_next_relevant_record(in_err_msg); /* OOFEM domain record */ get_next_relevant_record(in_err_msg); /* OOFEM output manager record */ get_next_relevant_record(in_err_msg); /* OOFEM component size record */ } #endif /* OOFEM_PAR end */ length = (int)strlen(string = line_buffer); for(i = 0; i < length; i++, string++){ /* obligatory components */ if(strncasecmp(string, "ncrosssect", 10) == 0){ /* number of cross sections */ if(csect_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 10; sscanf(string, "%d", &csect); csect_spec = obligatory = YES; } if(strncasecmp(string, "nmat", 4) == 0){ /* number of materials */ if(mater_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 4; sscanf(string, "%d", &mater); mater_spec = obligatory = YES; } if(strncasecmp(string, "nbc", 3) == 0){ /* number of boundary conditions */ if(bcond_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 3; sscanf(string, "%d", &bcond); bcond_spec = obligatory = YES; } if(strncasecmp(string, "nic", 3) == 0){ /* number of initial conditions */ if(nic_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 3; sscanf(string, "%d", &nic); nic_spec = obligatory = YES; } if(strncasecmp(string, "nltf", 4) == 0){ /* number of load time functions */ if(timef_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 4; sscanf(string, "%d", &timef); timef_spec = obligatory = YES; } /* optional components */ if(strncasecmp(string, "nbarrier", 8) == 0){ /* number of nonlocal barriers */ if(barriers_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 8; sscanf(string, "%d", &barriers); barriers_spec = optional = YES; } if(strncasecmp(string, "nrandgen", 8) == 0){ /* number of random field generators */ if(randgens_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 8; sscanf(string, "%d", &randgens); randgens_spec = optional = YES; } if(strncasecmp(string, "topology", 8) == 0){ /* topology type */ if(topology_spec == YES)error_message("Duplicity in component size record", GENERAL_ERROR); string += 8; sscanf(string, "%s", topology); topology_spec = optional = YES; } } if(obligatory == YES || optional == YES){ if(csect_spec == NO)error_message("Missing number of cross sections ", GENERAL_ERROR); if(mater_spec == NO)error_message("Missing number of materials", GENERAL_ERROR); if(bcond_spec == NO)error_message("Missing number of boundary conditions", GENERAL_ERROR); if(nic_spec == NO)error_message("Missing number of initial contitions", GENERAL_ERROR); if(timef_spec == NO)error_message("Missing number of load time functions", GENERAL_ERROR); } else{ /* process record without keywords (backward compatibility with older ctrl files, ordering of records prescribed) */ if(sscanf(line_buffer, "%d %d %d %d %d", &csect, &mater, &bcond, &nic, &timef) != 5){ sprintf(err_msg, "File %s reading error", control_name); error_message(err_msg, FILE_READ_ERROR); } } /* skip cross section, material, barrier, random field generator, boundary condition, initial condition and load time function records */ records = csect + mater + barriers + randgens + bcond + nic + timef; while(records--){ get_next_relevant_record(in_err_msg); } while((token = get_next_first_token(NULL)) != NULL){ key = get_token_key(token, keyword, KEY_NUM); switch(key){ case VERTEX: case CURVE: case SURFACE: case PATCH: case SHELL: case REGION: case INTERFACE: if(property_select == YES && specification == NO){ sprintf(err_msg, "Keyword %s not expected together with any entity keyword", keyword[PROPERTY]); error_message(err_msg, GENERAL_ERROR); } if(specification == YES){ if(entity_select == YES){ if(vertex_select == YES)deselect_entity_list(vertex_list); if(curve_select == YES)deselect_entity_list(curve_list); if(surface_select == YES)deselect_entity_list(surface_list); if(patch_select == YES)deselect_entity_list(patch_list); if(shell_select == YES)deselect_entity_list(shell_list); if(region_select == YES)deselect_entity_list(region_list); if(interface_select == YES)deselect_entity_list(interface_list); vertex_select = curve_select = surface_select = patch_select = shell_select = region_select = interface_select = NO; } if(property_select == YES){ deselect_entity_list(vertex_list); deselect_entity_list(curve_list); deselect_entity_list(surface_list); deselect_entity_list(patch_list); deselect_entity_list(shell_list); deselect_entity_list(region_list); deselect_entity_list(interface_list); } entity_select = property_select = specification = NO; } entity_select = YES; break; case PROPERTY: if(entity_select == YES && specification == NO){ sprintf(err_msg, "Keyword %s not expected together with any entity keyword", keyword[PROPERTY]); error_message(err_msg, GENERAL_ERROR); } if(specification == YES){ if(entity_select == YES){ if(vertex_select == YES)deselect_entity_list(vertex_list); if(curve_select == YES)deselect_entity_list(curve_list); if(surface_select == YES)deselect_entity_list(surface_list); if(patch_select == YES)deselect_entity_list(patch_list); if(shell_select == YES)deselect_entity_list(shell_list); if(region_select == YES)deselect_entity_list(region_list); if(interface_select == YES)deselect_entity_list(interface_list); vertex_select = curve_select = surface_select = patch_select = shell_select = region_select = interface_select = NO; } if(property_select == YES){ deselect_entity_list(vertex_list); deselect_entity_list(curve_list); deselect_entity_list(surface_list); deselect_entity_list(patch_list); deselect_entity_list(shell_list); deselect_entity_list(region_list); deselect_entity_list(interface_list); } entity_select = property_select = specification = NO; } property_select = YES; break; case WIDTH: if(entity_select == NO && property_select == NO) error_message("Entity or property specification missing", GENERAL_ERROR); specification = YES; break; case MASTERSLAVE: /* not used */ if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); process_entity_pair_list(); break; case MASTER: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not expected", GENERAL_ERROR); break; case NODEPROP: case ELEMPROP: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not allowed", GENERAL_ERROR); if((token = get_next_token(NULL)) == NULL) error_message("Missing node or element property", GENERAL_ERROR); /* do not use line_buffer (memory overlapping may occur) */ *temp_buffer = '0円'; while(token != NULL){ /* each token must be preceeded by space */ strcat(temp_buffer, " "); strcat(temp_buffer, token); token = get_next_token(NULL); } string = store_string(temp_buffer); string_list = add_item_to_list_head(string_list, (void *)string); specification = YES; break; case ELEMTYPE: /* for compatibility reasons */ case EDGETYPE: case TRIATYPE: case QUADTYPE: case TETRATYPE: case HEXATYPE: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not allowed", GENERAL_ERROR); if((token = get_next_token(NULL)) == NULL) error_message("Missing element type", GENERAL_ERROR); string = store_string(token); string_list = add_item_to_list_head(string_list, (void *)string); if((token = get_next_token(NULL)) != NULL) error_message("Redundant element type specification detected", GENERAL_ERROR); specification = YES; break; case ELEMWEIGHT: case EDGEWEIGHT: case TRIAWEIGHT: case QUADWEIGHT: case TETRAWEIGHT: case PYRAMWEIGHT: case WEDGEWEIGHT: case HEXAWEIGHT: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not allowed", GENERAL_ERROR); specification = YES; break; case BLOAD: case BOUNDARYLOAD: case BCODE: case BOUNDARYCODE: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not allowed", GENERAL_ERROR); specification = YES; break; case PARTITION: if(entity_select == NO) error_message("Entity specification missing", GENERAL_ERROR); if(property_select == YES) error_message("Property specification not allowed", GENERAL_ERROR); part_id = get_next_int("Partition number missing"); if(static_dd == YES && part_id <= 0) error_message("Positive partition id required", GENERAL_ERROR); if(static_dd == NO && part_id < 0) error_message("Nonnegative partition id required", GENERAL_ERROR); specification = YES; break; case CANCEL: if(entity_select == YES){ if(vertex_select == YES)deselect_entity_list(vertex_list); if(curve_select == YES)deselect_entity_list(curve_list); if(surface_select == YES)deselect_entity_list(surface_list); if(patch_select == YES)deselect_entity_list(patch_list); if(shell_select == YES)deselect_entity_list(shell_list); if(region_select == YES)deselect_entity_list(region_list); if(interface_select == YES)deselect_entity_list(interface_list); vertex_select = curve_select = surface_select = patch_select = shell_select = region_select = interface_select = NO; } if(property_select == YES){ deselect_entity_list(vertex_list); deselect_entity_list(curve_list); deselect_entity_list(surface_list); deselect_entity_list(patch_list); deselect_entity_list(shell_list); deselect_entity_list(region_list); deselect_entity_list(interface_list); } entity_select = property_select = specification = NO; specification = NO; break; default: sprintf(err_msg, "Unexpected or invalid keyword \"%s\" encountered", token); error_message(err_msg, GENERAL_ERROR); } switch(key){ case VERTEX: case CURVE: case SURFACE: case PATCH: case SHELL: case REGION: case INTERFACE: process_entity_list(); break; case PROPERTY: process_property_list(); break; case WIDTH: width = get_next_fpn("Width specification missing"); if(width < 0.0) error_message("Negative width not allowed", GENERAL_ERROR); apply_width(width); break; case NODEPROP: apply_properties((void *)string, NODE_PROP_KEY); break; case ELEMPROP: apply_properties((void *)string, ELEM_PROP_KEY); break; case ELEMTYPE: case EDGETYPE: case TRIATYPE: case QUADTYPE: case TETRATYPE: case HEXATYPE: apply_elem_type(string); break; case ELEMWEIGHT: case EDGEWEIGHT: case TRIAWEIGHT: case QUADWEIGHT: case TETRAWEIGHT: case PYRAMWEIGHT: case WEDGEWEIGHT: case HEXAWEIGHT: weight = get_next_int("Weight specification missing"); if(weight <= 0) error_message("Positive weight required", GENERAL_ERROR); apply_weight(weight); weight_flag = 2; /* 2 refers to vertex weight in Metis */ break; case BLOAD: case BOUNDARYLOAD: load_id = 0; while((token = get_next_token(NULL)) != NULL){ if((load_id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid boundary load id (%ld)", load_id); error_message(err_msg, GENERAL_ERROR); } if((ident = get_id(id_list, load_id)) == NULL){ ident = create_id(load_id); id_list = add_item_to_list_head(id_list, (void *)ident); } apply_properties((void *)ident, BOUNDARYLOAD_PROP_KEY); } if(load_id == 0){ sprintf(err_msg, "Missing boundary load id"); error_message(err_msg, GENERAL_ERROR); } break; case BCODE: case BOUNDARYCODE: code_id = 0; while((token = get_next_token(NULL)) != NULL){ if((load_id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid boundary code id (%ld)", code_id); error_message(err_msg, GENERAL_ERROR); } if((ident = get_id(id_list, code_id)) == NULL){ ident = create_id(code_id); id_list = add_item_to_list_head(id_list, (void *)ident); } apply_properties((void *)ident, BOUNDARYCODE_PROP_KEY); } if(code_id == 0){ sprintf(err_msg, "Missing boundary code id"); error_message(err_msg, GENERAL_ERROR); } break; case PARTITION: #ifdef METIS if(static_dd == YES){ if(part_id < min_dd)min_dd = part_id; if(part_id> max_dd)max_dd = part_id; } #endif apply_partition(part_id); break; case MASTER: master_spec = YES; master_id = 0; while((token = get_next_token(NULL)) != NULL){ master_id = get_int_from_token(token); if(master_id <= 0 || master_id> nodes){ sprintf(err_msg, "Invalid number of master node (%ld)", master_id); error_message(err_msg, GENERAL_ERROR); } node_array[master_id - 1].master = YES; #ifdef MASTER_SLAVE apply_master(master_id); #endif } if(master_id == 0){ sprintf(err_msg, "Missing master specification"); error_message(err_msg, GENERAL_ERROR); } break; case CANCEL: break; default: sprintf(err_msg, "Unexpected or invalid keyword \"%s\" encountered", token); error_message(err_msg, GENERAL_ERROR); } } if(specification == NO){ if(entity_select == YES) error_message("Entity properties missing", GENERAL_ERROR); if(property_select == YES) error_message("Property properties missing", GENERAL_ERROR); } if(entity_select == YES){ if(vertex_select == YES)deselect_entity_list(vertex_list); if(curve_select == YES)deselect_entity_list(curve_list); if(surface_select == YES)deselect_entity_list(surface_list); if(patch_select == YES)deselect_entity_list(patch_list); if(shell_select == YES)deselect_entity_list(shell_list); if(region_select == YES)deselect_entity_list(region_list); if(interface_select == YES)deselect_entity_list(interface_list); vertex_select = curve_select = surface_select = patch_select = shell_select = region_select = interface_select = NO; } if(property_select == YES){ deselect_entity_list(vertex_list); deselect_entity_list(curve_list); deselect_entity_list(surface_list); deselect_entity_list(patch_list); deselect_entity_list(shell_list); deselect_entity_list(region_list); deselect_entity_list(interface_list); } entity_select = property_select = specification = NO; reverse_entity_prop_list(vertex_list); reverse_entity_prop_list(curve_list); reverse_entity_prop_list(surface_list); reverse_entity_prop_list(patch_list); reverse_entity_prop_list(shell_list); reverse_entity_prop_list(region_list); reverse_entity_prop_list(interface_list); #ifdef METIS if(static_dd == YES){ if(min_dd != 1) error_message("Partition id not starting from 1", GENERAL_ERROR); if(nparts != max_dd) error_message("Number of static partitions is not consistent with -np option", GENERAL_ERROR); nparts = max_dd; if(renum == YES && nparts == 1){ fprintf(stderr, "WARNING: Renumbered mesh ==> node renumbering ignored.\n"); renum = NO; } if(nparts != 1){ if(nparts> 1000) error_message("Too many partitions", GENERAL_ERROR); if((dd_number = (int *)calloc(max_dd, sizeof(int))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); entity_list = curve_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } entity_list = surface_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } entity_list = patch_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } entity_list = shell_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } entity_list = region_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } entity_list = interface_list; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> output == YES)dd_number[entity -> partition_id - 1] = 1; } for(i = 0; i < max_dd; i++){ if(dd_number[i] == 0) error_message("Partition numbering not continuous", GENERAL_ERROR); } free(dd_number); } } #endif if(elems < nparts) error_message("Too many partitions required", GENERAL_ERROR); if(renum == YES || nparts> 1){ if((node_num_elems = (long *)calloc(nodes + 1, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* count number of elements incident to nodes (this can be done when reading the mesh) */ fe_edge = edge_array; for(i = 0; i < edges; i++, fe_edge++){ for(j = 0; j < 2; j++){ nd = fe_edge -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_face = face_array; for(i = 0; i < faces; i++, fe_face++){ for(j = 0; j < 3; j++){ nd = fe_face -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_quad = quad_array; for(i = 0; i < quads; i++, fe_quad++){ for(j = 0; j < 4; j++){ nd = fe_quad -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_tetra = tetra_array; for(i = 0; i < tetras; i++, fe_tetra++){ for(j = 0; j < 4; j++){ nd = fe_tetra -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_pyram = pyram_array; for(i = 0; i < pyrams; i++, fe_pyram++){ for(j = 0; j < 5; j++){ nd = fe_pyram -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_wedge = wedge_array; for(i = 0; i < wedges; i++, fe_wedge++){ for(j = 0; j < 6; j++){ nd = fe_wedge -> node[j] -> id; node_num_elems[nd - 1]++; } } fe_hexa = hexa_array; for(i = 0; i < hexas; i++, fe_hexa++){ for(j = 0; j < 8; j++){ nd = fe_hexa -> node[j] -> id; node_num_elems[nd - 1]++; } } /* recalculate the number of elements to current addresses */ pos = 0; for(i = 0; i < nodes; i++){ number = node_num_elems[i]; node_num_elems[i] = pos; pos += number; } node_num_elems[nodes] = size = pos; if((node_con_elems = (long *)calloc(size, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* store element numbers incident to nodes */ fe_edge = edge_array; for(i = 0; i < edges; i++, fe_edge++){ for(j = 0; j < 2; j++){ nd = fe_edge -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1; } } fe_face = face_array; for(i = 0; i < faces; i++, fe_face++){ for(j = 0; j < 3; j++){ nd = fe_face -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges; } } fe_quad = quad_array; for(i = 0; i < quads; i++, fe_quad++){ for(j = 0; j < 4; j++){ nd = fe_quad -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges + faces; } } fe_tetra = tetra_array; for(i = 0; i < tetras; i++, fe_tetra++){ for(j = 0; j < 4; j++){ nd = fe_tetra -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges + faces + quads; } } fe_pyram = pyram_array; for(i = 0; i < pyrams; i++, fe_pyram++){ for(j = 0; j < 5; j++){ nd = fe_pyram -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges + faces + quads + tetras; } } fe_wedge = wedge_array; for(i = 0; i < wedges; i++, fe_wedge++){ for(j = 0; j < 6; j++){ nd = fe_wedge -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges + faces + quads + tetras + pyrams; } } fe_hexa = hexa_array; for(i = 0; i < hexas; i++, fe_hexa++){ for(j = 0; j < 8; j++){ nd = fe_hexa -> node[j] -> id; node_con_elems[node_num_elems[nd - 1]++] = i + 1 + edges + faces + quads + tetras + pyrams + wedges; } } /* recalculate the addresses to address of the first element */ pos = 0; for(i = 0; i < nodes; i++){ number = node_num_elems[i] - pos; node_num_elems[i] = pos; pos += number; } } if(renum == YES){ if((nd_num_nodes = (long *)calloc(nodes + 1, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* note: the following part is equivalent to element-cut connectivity; however nd_num_nodes and nd_con_nodes arrays of type long instead of type idxtype (required by Metis) are used */ /* count number of nodes incident to nodes */ for(i = 0; i < nodes; i++){ node = i + 1; for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++){ nd = fe_edge -> node[k] -> id; if(nd != node && nd> 0){ fe_edge -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++){ nd = fe_face -> node[k] -> id; if(nd != node && nd> 0){ fe_face -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_quad -> node[k] -> id; if(nd != node && nd> 0){ fe_quad -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_tetra -> node[k] -> id; if(nd != node && nd> 0){ fe_tetra -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++){ nd = fe_pyram -> node[k] -> id; if(nd != node && nd> 0){ fe_pyram -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++){ nd = fe_wedge -> node[k] -> id; if(nd != node && nd> 0){ fe_wedge -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++){ nd = fe_hexa -> node[k] -> id; if(nd != node && nd> 0){ fe_hexa -> node[k] -> id = -nd; nd_num_nodes[i]++; } } break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } /* restore connected node id to positive value */ for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++)fe_edge -> node[k] -> id = abs(fe_edge -> node[k] -> id); break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++)fe_face -> node[k] -> id = abs(fe_face -> node[k] -> id); break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++)fe_quad -> node[k] -> id = abs(fe_quad -> node[k] -> id); break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++)fe_tetra -> node[k] -> id = abs(fe_tetra -> node[k] -> id); break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++)fe_pyram -> node[k] -> id = abs(fe_pyram -> node[k] -> id); break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++)fe_wedge -> node[k] -> id = abs(fe_wedge -> node[k] -> id); break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++)fe_hexa -> node[k] -> id = abs(fe_hexa -> node[k] -> id); break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } } /* recalculate the number of nodes to current addresses */ pos = 0; for(i = 0; i < nodes; i++){ number = nd_num_nodes[i]; nd_num_nodes[i] = pos; pos += number; } nd_num_nodes[nodes] = size = pos; if((nd_con_nodes = (long *)calloc(size, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if(nparts> 1){ if((nd_con_nds = (long *)calloc(size, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } /* store nodes incident to nodes */ for(i = 0; i < nodes; i++){ node = i + 1; for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++){ nd = fe_edge -> node[k] -> id; if(nd != node && nd> 0){ fe_edge -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++){ nd = fe_face -> node[k] -> id; if(nd != node && nd> 0){ fe_face -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_quad -> node[k] -> id; if(nd != node && nd> 0){ fe_quad -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_tetra -> node[k] -> id; if(nd != node && nd> 0){ fe_tetra -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++){ nd = fe_pyram -> node[k] -> id; if(nd != node && nd> 0){ fe_pyram -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++){ nd = fe_wedge -> node[k] -> id; if(nd != node && nd> 0){ fe_wedge -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++){ nd = fe_hexa -> node[k] -> id; if(nd != node && nd> 0){ fe_hexa -> node[k] -> id = -nd; nd_con_nodes[nd_num_nodes[i]++] = nd; } } break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } /* restore connected node id to positive value */ for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++)fe_edge -> node[k] -> id = abs(fe_edge -> node[k] -> id); break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++)fe_face -> node[k] -> id = abs(fe_face -> node[k] -> id); break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++)fe_quad -> node[k] -> id = abs(fe_quad -> node[k] -> id); break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++)fe_tetra -> node[k] -> id = abs(fe_tetra -> node[k] -> id); break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++)fe_pyram -> node[k] -> id = abs(fe_pyram -> node[k] -> id); break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++)fe_wedge -> node[k] -> id = abs(fe_wedge -> node[k] -> id); break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++)fe_hexa -> node[k] -> id = abs(fe_hexa -> node[k] -> id); break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } } /* recalculate the addresses to address of the first node */ pos = 0; for(i = 0; i < nodes; i++){ number = nd_num_nodes[i] - pos; nd_num_nodes[i] = pos; pos += number; } #ifdef DEBUG for(i = 0; i < nodes; i++){ fprintf(stdout, "node %ld: %ld:", i + 1, nd_num_nodes[i + 1] - nd_num_nodes[i]); for(j = nd_num_nodes[i]; j < nd_num_nodes[i + 1]; j++){ fprintf(stdout, " %ld", (long)(nd_con_nodes[j])); } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); #endif } #ifdef METIS if(nparts> 1){ if(elem_cut == YES){ if((node_num_nodes = (idxtype *)calloc(nodes + 1, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(node_cut == YES){ if((elem_num_elems = (idxtype *)calloc(elems + 1, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if((node_part = (idxtype *)calloc(nodes, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if((elem_part = (idxtype *)calloc(elems, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if((remote_node = (int *)calloc(nodes, sizeof(int))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if((remote_elem = (int *)calloc(elems, sizeof(int))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if((part_flag = (logic *)calloc(nparts, sizeof(logic))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); for(i = 0; i < nparts; i++)part_flag[i] = NO; if(elem_cut == YES){ /* count number of edges incident to nodes */ for(i = 0; i < nodes; i++){ node = i + 1; for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++){ nd = fe_edge -> node[k] -> id; if(nd != node && nd> 0){ fe_edge -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++){ nd = fe_face -> node[k] -> id; if(nd != node && nd> 0){ fe_face -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_quad -> node[k] -> id; if(nd != node && nd> 0){ fe_quad -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_tetra -> node[k] -> id; if(nd != node && nd> 0){ fe_tetra -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++){ nd = fe_pyram -> node[k] -> id; if(nd != node && nd> 0){ fe_pyram -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++){ nd = fe_wedge -> node[k] -> id; if(nd != node && nd> 0){ fe_wedge -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++){ nd = fe_hexa -> node[k] -> id; if(nd != node && nd> 0){ fe_hexa -> node[k] -> id = -nd; node_num_nodes[i]++; } } break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } /* restore connected node id to positive value */ for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++)fe_edge -> node[k] -> id = abs(fe_edge -> node[k] -> id); break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++)fe_face -> node[k] -> id = abs(fe_face -> node[k] -> id); break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++)fe_quad -> node[k] -> id = abs(fe_quad -> node[k] -> id); break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++)fe_tetra -> node[k] -> id = abs(fe_tetra -> node[k] -> id); break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++)fe_pyram -> node[k] -> id = abs(fe_pyram -> node[k] -> id); break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++)fe_wedge -> node[k] -> id = abs(fe_wedge -> node[k] -> id); break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++)fe_hexa -> node[k] -> id = abs(fe_hexa -> node[k] -> id); break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } } /* recalculate the number of edges to current addresses */ pos = 0; for(i = 0; i < nodes; i++){ number = node_num_nodes[i]; node_num_nodes[i] = pos; pos += number; } node_num_nodes[nodes] = size = pos; if((node_con_nodes = (idxtype *)calloc(size, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* store other node numbers of edges incident to nodes (Fortran style !!!) */ for(i = 0; i < nodes; i++){ node = i + 1; for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++){ nd = fe_edge -> node[k] -> id; if(nd != node && nd> 0){ fe_edge -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++){ nd = fe_face -> node[k] -> id; if(nd != node && nd> 0){ fe_face -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_quad -> node[k] -> id; if(nd != node && nd> 0){ fe_quad -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++){ nd = fe_tetra -> node[k] -> id; if(nd != node && nd> 0){ fe_tetra -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++){ nd = fe_pyram -> node[k] -> id; if(nd != node && nd> 0){ fe_pyram -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++){ nd = fe_wedge -> node[k] -> id; if(nd != node && nd> 0){ fe_wedge -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++){ nd = fe_hexa -> node[k] -> id; if(nd != node && nd> 0){ fe_hexa -> node[k] -> id = -nd; node_con_nodes[node_num_nodes[i]++] = nd; } } break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } /* restore connected node id to positive value */ for(j = node_num_elems[i]; j < node_num_elems[node]; j++){ elem = node_con_elems[j]; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(k = 0; k < 2; k++)fe_edge -> node[k] -> id = abs(fe_edge -> node[k] -> id); break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(k = 0; k < 3; k++)fe_face -> node[k] -> id = abs(fe_face -> node[k] -> id); break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(k = 0; k < 4; k++)fe_quad -> node[k] -> id = abs(fe_quad -> node[k] -> id); break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(k = 0; k < 4; k++)fe_tetra -> node[k] -> id = abs(fe_tetra -> node[k] -> id); break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(k = 0; k < 5; k++)fe_pyram -> node[k] -> id = abs(fe_pyram -> node[k] -> id); break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(k = 0; k < 6; k++)fe_wedge -> node[k] -> id = abs(fe_wedge -> node[k] -> id); break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(k = 0; k < 8; k++)fe_hexa -> node[k] -> id = abs(fe_hexa -> node[k] -> id); break; default: error_message("Invalid element number", GENERAL_ERROR); break; } } } /* recalculate the addresses to address of the first node (Fortran style !!!!) */ pos = 0; for(i = 0; i < nodes; i++){ number = node_num_nodes[i] - pos; node_num_nodes[i] = pos + 1; pos += number; } node_num_nodes[nodes]++; #ifdef DEBUG for(i = 0; i < nodes; i++){ fprintf(stdout, "node %ld: %ld:", i + 1, (long)(node_num_nodes[i + 1] - node_num_nodes[i])); for(j = node_num_nodes[i] - 1; j < node_num_nodes[i + 1] - 1; j++){ fprintf(stdout, " %ld", (long)(node_con_nodes[j])); } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); #endif } if(node_cut == YES){ /* count number of elements neighbouring with elements */ fe_edge = edge_array; /* all elements */ for(i = 0; i < edges; i++, fe_edge++){ elem1 = global_edge_id(i) + 1; /* macro */ node1 = fe_edge -> node[0] -> id; node2 = fe_edge -> node[1] -> id; for(j = node_num_elems[node1 - 1]; j < node_num_elems[node1]; j++){ elem2 = node_con_elems[j]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; continue; } for(k = node_num_elems[node2 - 1]; k < node_num_elems[node2]; k++){ if(elem2 == node_con_elems[k]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; break; } } } } fe_face = face_array; /* only tetras, pyrams and wedges sharing face */ for(i = 0; i < faces; i++, fe_face++){ if(fe_face -> entity -> boundary == NO)continue; count = 0; elem1 = global_face_id(i) + 1; /* macro */ node1 = fe_face -> node[0] -> id; node2 = fe_face -> node[1] -> id; node3 = fe_face -> node[2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_tetra(elem2) == YES){ fe_tetra = &(tetra_array[local_tetra_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_tetra -> entity && fe_face -> entity -> ngb_ent[1] != fe_tetra -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } } if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_pyram -> entity && fe_face -> entity -> ngb_ent[1] != fe_pyram -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_wedge -> entity && fe_face -> entity -> ngb_ent[1] != fe_wedge -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } } if(count == 2)break; } } fe_face = face_array; /* all except edges and except tetras, pyrams and wedges sharing face */ for(i = 0; i < faces; i++, fe_face++){ elem1 = global_face_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 3; for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; elem_num_elems[elem1 - 1]--; j1 = face_ed_nd[j][0]; j2 = face_ed_nd[j][1]; node1 = fe_face -> node[j1] -> id; node2 = fe_face -> node[j2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES)continue; if(is_tetra(elem2) == YES){ fe_tetra = &(tetra_array[local_tetra_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_tetra -> entity || fe_face -> entity -> ngb_ent[1] == fe_tetra -> entity)continue; } if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_pyram -> entity || fe_face -> entity -> ngb_ent[1] == fe_pyram -> entity)continue; } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_wedge -> entity || fe_face -> entity -> ngb_ent[1] == fe_wedge -> entity)continue; } for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 == node_con_elems[m]){ elem_num_elems[elem1 - 1]++; if(is_edge(elem2) == NO && is_face(elem2) == NO)elem_num_elems[elem2 - 1]++; break; } } } } } fe_quad = quad_array; /* only pyrams, wedges and hexas sharing quad */ for(i = 0; i < quads; i++, fe_quad++){ if(fe_quad -> entity -> boundary == NO)continue; count = 0; elem1 = global_quad_id(i) + 1; /* macro */ node1 = fe_quad -> node[0] -> id; node2 = fe_quad -> node[1] -> id; node3 = fe_quad -> node[2] -> id; node4 = fe_quad -> node[3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_pyram -> entity && fe_quad -> entity -> ngb_ent[1] != fe_pyram -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } break; } } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_wedge -> entity && fe_quad -> entity -> ngb_ent[1] != fe_wedge -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } break; } } if(is_hexa(elem2) == YES){ fe_hexa = &(hexa_array[local_hexa_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_hexa -> entity && fe_quad -> entity -> ngb_ent[1] != fe_hexa -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; elem_num_elems[elem2 - 1]++; count++; break; } } break; } break; } } if(count == 2)break; } } fe_quad = quad_array; /* all except edges, faces and except pyram, wedges and hexas sharing quad */ for(i = 0; i < quads; i++, fe_quad++){ elem1 = global_quad_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 4; for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; elem_num_elems[elem1 - 1]--; j1 = quad_ed_nd[j][0]; j2 = quad_ed_nd[j][1]; node1 = fe_quad -> node[j1] -> id; node2 = fe_quad -> node[j2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES || is_face(elem2) == YES)continue; if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_pyram -> entity || fe_quad -> entity -> ngb_ent[1] == fe_pyram -> entity)continue; } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_wedge -> entity || fe_quad -> entity -> ngb_ent[1] == fe_wedge -> entity)continue; } if(is_hexa(elem2) == YES){ fe_hexa = &(hexa_array[local_hexa_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_hexa -> entity || fe_quad -> entity -> ngb_ent[1] == fe_hexa -> entity)continue; } for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 == node_con_elems[m]){ elem_num_elems[elem1 - 1]++; if(is_edge(elem2) == NO && is_face(elem2) == NO && is_quad(elem2) == NO)elem_num_elems[elem2 - 1]++; break; } } } } } fe_tetra = tetra_array; /* only tetras */ for(i = 0; i < tetras; i++, fe_tetra++){ elem1 = global_tetra_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 4; for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; count = 0; elem_num_elems[elem1 - 1]--; j1 = tetra_fc_nd[j][0]; j2 = tetra_fc_nd[j][1]; j3 = tetra_fc_nd[j][2]; node1 = fe_tetra -> node[j1] -> id; node2 = fe_tetra -> node[j2] -> id; node3 = fe_tetra -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } } } fe_pyram = pyram_array; /* only pyrams */ for(i = 0; i < pyrams; i++, fe_pyram++){ elem1 = global_pyram_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 5; j = 0; if((fe_pyram -> bflag & (1 << j)) != 0){ count = 0; elem_num_elems[elem1 - 1]--; j1 = pyram_fc_nd[j][0]; j2 = pyram_fc_nd[j][1]; j3 = pyram_fc_nd[j][2]; j4 = pyram_fc_nd[j][3]; node1 = fe_pyram -> node[j1] -> id; node2 = fe_pyram -> node[j2] -> id; node3 = fe_pyram -> node[j3] -> id; node4 = fe_pyram -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } } for(j = 1; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; count = 0; elem_num_elems[elem1 - 1]--; j1 = pyram_fc_nd[j][0]; j2 = pyram_fc_nd[j][1]; j3 = pyram_fc_nd[j][2]; node1 = fe_pyram -> node[j1] -> id; node2 = fe_pyram -> node[j2] -> id; node3 = fe_pyram -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } } } fe_wedge = wedge_array; /* only wedges */ for(i = 0; i < wedges; i++, fe_wedge++){ elem1 = global_wedge_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 5; for(j = 0; j < 2; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; count = 0; elem_num_elems[elem1 - 1]--; j1 = wedge_fc_nd[j][0]; j2 = wedge_fc_nd[j][1]; j3 = wedge_fc_nd[j][2]; node1 = fe_wedge -> node[j1] -> id; node2 = fe_wedge -> node[j2] -> id; node3 = fe_wedge -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } } for(j = 2; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; count = 0; elem_num_elems[elem1 - 1]--; j1 = wedge_fc_nd[j][0]; j2 = wedge_fc_nd[j][1]; j3 = wedge_fc_nd[j][2]; j4 = wedge_fc_nd[j][3]; node1 = fe_wedge -> node[j1] -> id; node2 = fe_wedge -> node[j2] -> id; node3 = fe_wedge -> node[j3] -> id; node4 = fe_wedge -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } } } fe_hexa = hexa_array; /* only hexas */ for(i = 0; i < hexas; i++, fe_hexa++){ elem1 = global_hexa_id(i) + 1; /* macro */ elem_num_elems[elem1 - 1] += 6; for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; count = 0; elem_num_elems[elem1 - 1]--; j1 = hexa_fc_nd[j][0]; j2 = hexa_fc_nd[j][1]; j3 = hexa_fc_nd[j][2]; j4 = hexa_fc_nd[j][3]; node1 = fe_hexa -> node[j1] -> id; node2 = fe_hexa -> node[j2] -> id; node3 = fe_hexa -> node[j3] -> id; node4 = fe_hexa -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_num_elems[elem1 - 1]++; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } } } /* recalculate the number of elements to current addresses */ pos = 0; for(i = 0; i < elems; i++){ number = elem_num_elems[i]; elem_num_elems[i] = pos; pos += number; } if(pos / 2 * 2 != pos) error_message("Internal error", GENERAL_ERROR); elem_num_elems[elems] = size = pos; if((elem_con_elems = (idxtype *)calloc(size, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* store element numbers neighbouring with elements (Fortran style !!!) */ fe_edge = edge_array; /* all elements */ for(i = 0; i < edges; i++, fe_edge++){ elem1 = global_edge_id(i) + 1; /* macro */ node1 = fe_edge -> node[0] -> id; node2 = fe_edge -> node[1] -> id; for(j = node_num_elems[node1 - 1]; j < node_num_elems[node1]; j++){ elem2 = node_con_elems[j]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; continue; } for(k = node_num_elems[node2 - 1]; k < node_num_elems[node2]; k++){ if(elem2 == node_con_elems[k]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; break; } } } } fe_face = face_array; /* only tetras, pyrams and wedges sharing face */ for(i = 0; i < faces; i++, fe_face++){ if(fe_face -> entity -> boundary == NO)continue; count = 0; elem1 = global_face_id(i) + 1; /* macro */ node1 = fe_face -> node[0] -> id; node2 = fe_face -> node[1] -> id; node3 = fe_face -> node[2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_tetra(elem2) == YES){ fe_tetra = &(tetra_array[local_tetra_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_tetra -> entity && fe_face -> entity -> ngb_ent[1] != fe_tetra -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } } if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_pyram -> entity && fe_face -> entity -> ngb_ent[1] != fe_pyram -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] != fe_wedge -> entity && fe_face -> entity -> ngb_ent[1] != fe_wedge -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } } if(count == 2)break; } } fe_face = face_array; /* all except edges and except tetras, pyrams and wedges sharing face */ for(i = 0; i < faces; i++, fe_face++){ elem1 = global_face_id(i) + 1; /* macro */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0) bflag = NO; else bflag = YES; count = 0; j1 = face_ed_nd[j][0]; j2 = face_ed_nd[j][1]; node1 = fe_face -> node[j1] -> id; node2 = fe_face -> node[j2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES)continue; if(is_tetra(elem2) == YES){ fe_tetra = &(tetra_array[local_tetra_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_tetra -> entity || fe_face -> entity -> ngb_ent[1] == fe_tetra -> entity)continue; } if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_pyram -> entity || fe_face -> entity -> ngb_ent[1] == fe_pyram -> entity)continue; } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_face -> entity -> ngb_ent[0] == fe_wedge -> entity || fe_face -> entity -> ngb_ent[1] == fe_wedge -> entity)continue; } for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 == node_con_elems[m]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; if(is_edge(elem2) == NO && is_face(elem2) == NO) elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } if(count == 1 && bflag == NO)break; } } } fe_quad = quad_array; /* only pyrams, wedges and hexas sharing quad */ for(i = 0; i < quads; i++, fe_quad++){ if(fe_quad -> entity -> boundary == NO)continue; count = 0; elem1 = global_quad_id(i) + 1; /* macro */ node1 = fe_quad -> node[0] -> id; node2 = fe_quad -> node[1] -> id; node3 = fe_quad -> node[2] -> id; node4 = fe_quad -> node[3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_pyram -> entity && fe_quad -> entity -> ngb_ent[1] != fe_pyram -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } break; } } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_wedge -> entity && fe_quad -> entity -> ngb_ent[1] != fe_wedge -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } break; } } if(is_hexa(elem2) == YES){ fe_hexa = &(hexa_array[local_hexa_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] != fe_hexa -> entity && fe_quad -> entity -> ngb_ent[1] != fe_hexa -> entity)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } break; } break; } } if(count == 2)break; } } fe_quad = quad_array; /* all except edges, faces and except pyrams, wedges and hexas sharing quad */ for(i = 0; i < quads; i++, fe_quad++){ elem1 = global_quad_id(i) + 1; /* macro */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0) bflag = NO; else bflag = YES; count = 0; j1 = quad_ed_nd[j][0]; j2 = quad_ed_nd[j][1]; node1 = fe_quad -> node[j1] -> id; node2 = fe_quad -> node[j2] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_edge(elem2) == YES || is_face(elem2) == YES)continue; if(is_pyram(elem2) == YES){ fe_pyram = &(pyram_array[local_pyram_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_pyram -> entity || fe_quad -> entity -> ngb_ent[1] == fe_pyram -> entity)continue; } if(is_wedge(elem2) == YES){ fe_wedge = &(wedge_array[local_wedge_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_wedge -> entity || fe_quad -> entity -> ngb_ent[1] == fe_wedge -> entity)continue; } if(is_hexa(elem2) == YES){ fe_hexa = &(hexa_array[local_hexa_id(elem2) - 1]); /* macro */ if(fe_quad -> entity -> ngb_ent[0] == fe_hexa -> entity || fe_quad -> entity -> ngb_ent[1] == fe_hexa -> entity)continue; } for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 == node_con_elems[m]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; if(is_edge(elem2) == NO && is_face(elem2) == NO && is_quad(elem2) == NO) elem_con_elems[elem_num_elems[elem2 - 1]++] = elem1; count++; break; } } if(count == 1 && bflag == NO)break; } } } fe_tetra = tetra_array; /* only tetras */ for(i = 0; i < tetras; i++, fe_tetra++){ elem1 = global_tetra_id(i) + 1; /* macro */ for(j = 0; j < 4; j++){ count = 0; j1 = tetra_fc_nd[j][0]; j2 = tetra_fc_nd[j][1]; j3 = tetra_fc_nd[j][2]; node1 = fe_tetra -> node[j1] -> id; node2 = fe_tetra -> node[j2] -> id; node3 = fe_tetra -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; if(elem2 == elem1)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } } } fe_pyram = pyram_array; /* only pyrams */ for(i = 0; i < pyrams; i++, fe_pyram++){ elem1 = global_pyram_id(i) + 1; /* macro */ j = 0; count = 0; j1 = pyram_fc_nd[j][0]; j2 = pyram_fc_nd[j][1]; j3 = pyram_fc_nd[j][2]; j4 = pyram_fc_nd[j][3]; node1 = fe_pyram -> node[j1] -> id; node2 = fe_pyram -> node[j2] -> id; node3 = fe_pyram -> node[j3] -> id; node4 = fe_pyram -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } for(j = 1; j < 5; j++){ count = 0; j1 = pyram_fc_nd[j][0]; j2 = pyram_fc_nd[j][1]; j3 = pyram_fc_nd[j][2]; node1 = fe_pyram -> node[j1] -> id; node2 = fe_pyram -> node[j2] -> id; node3 = fe_pyram -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; if(elem2 == elem1)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } } } fe_wedge = wedge_array; /* only wedges */ for(i = 0; i < wedges; i++, fe_wedge++){ elem1 = global_wedge_id(i) + 1; /* macro */ for(j = 0; j < 2; j++){ count = 0; j1 = wedge_fc_nd[j][0]; j2 = wedge_fc_nd[j][1]; j3 = wedge_fc_nd[j][2]; node1 = fe_wedge -> node[j1] -> id; node2 = fe_wedge -> node[j2] -> id; node3 = fe_wedge -> node[j3] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(is_tetra(elem2) == NO && is_pyram(elem2) == NO && is_wedge(elem2) == NO)continue; if(elem2 == elem1)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 == node_con_elems[n]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } } for(j = 2; j < 5; j++){ count = 0; j1 = wedge_fc_nd[j][0]; j2 = wedge_fc_nd[j][1]; j3 = wedge_fc_nd[j][2]; j4 = wedge_fc_nd[j][3]; node1 = fe_wedge -> node[j1] -> id; node2 = fe_wedge -> node[j2] -> id; node3 = fe_wedge -> node[j3] -> id; node4 = fe_wedge -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } } } fe_hexa = hexa_array; /* only hexas */ for(i = 0; i < hexas; i++, fe_hexa++){ elem1 = global_hexa_id(i) + 1; /* macro */ for(j = 0; j < 6; j++){ count = 0; j1 = hexa_fc_nd[j][0]; j2 = hexa_fc_nd[j][1]; j3 = hexa_fc_nd[j][2]; j4 = hexa_fc_nd[j][3]; node1 = fe_hexa -> node[j1] -> id; node2 = fe_hexa -> node[j2] -> id; node3 = fe_hexa -> node[j3] -> id; node4 = fe_hexa -> node[j4] -> id; for(k = node_num_elems[node1 - 1]; k < node_num_elems[node1]; k++){ elem2 = node_con_elems[k]; if(elem2 == elem1)continue; if(is_pyram(elem2) == NO && is_wedge(elem2) == NO && is_hexa(elem2) == NO)continue; for(m = node_num_elems[node2 - 1]; m < node_num_elems[node2]; m++){ if(elem2 != node_con_elems[m])continue; for(n = node_num_elems[node3 - 1]; n < node_num_elems[node3]; n++){ if(elem2 != node_con_elems[n])continue; for(p = node_num_elems[node4 - 1]; p < node_num_elems[node4]; p++){ if(elem2 == node_con_elems[p]){ elem_con_elems[elem_num_elems[elem1 - 1]++] = elem2; count++; break; } } if(count == 1)break; } if(count == 1)break; } if(count == 1)break; } } } /* recalculate the addresses to address of the first element (Fortran style !!!!) */ pos = 0; for(i = 0; i < elems; i++){ number = elem_num_elems[i] - pos; elem_num_elems[i] = pos + 1; pos += number; } elem_num_elems[elems]++; #ifdef DEBUG for(i = 0; i < elems; i++){ elem_id = i + 1; type = elem_type(elem_id); /* macro */ switch(type){ case EDGE_ELEM: fprintf(stdout, "edge %ld:", local_edge_id(i) + 1); /* macro */ break; case FACE_ELEM: fprintf(stdout, "face %ld:", local_face_id(i) + 1); /* macro */ break; case QUAD_ELEM: fprintf(stdout, "quad %ld:", local_quad_id(i) + 1); /* macro */ break; case TETRA_ELEM: fprintf(stdout, "tetra %ld:", local_tetra_id(i) + 1); /* macro */ break; case PYRAM_ELEM: fprintf(stdout, "pyram %ld:", local_pyram_id(i) + 1); /* macro */ break; case WEDGE_ELEM: fprintf(stdout, "wedge %ld:", local_wedge_id(i) + 1); /* macro */ break; case HEXA_ELEM: fprintf(stdout, "hexa %ld:", local_hexa_id(i) + 1); /* macro */ break; } for(j = elem_num_elems[i] - 1; j < elem_num_elems[i + 1] - 1; j++){ elem_id = elem_con_elems[j]; type = elem_type(elem_id); /* macro */ switch(type){ case EDGE_ELEM: fprintf(stdout, " %ld(e)", local_edge_id(elem_id)); /* macro */ break; case FACE_ELEM: fprintf(stdout, " %ld(f)", local_face_id(elem_id)); /* macro */ break; case QUAD_ELEM: fprintf(stdout, " %ld(q)", local_quad_id(elem_id)); /* macro */ break; case TETRA_ELEM: fprintf(stdout, " %ld(t)", local_tetra_id(elem_id)); /* macro */ break; case PYRAM_ELEM: fprintf(stdout, " %ld(t)", local_pyram_id(elem_id)); /* macro */ break; case WEDGE_ELEM: fprintf(stdout, " %ld(t)", local_wedge_id(elem_id)); /* macro */ break; case HEXA_ELEM: fprintf(stdout, " %ld(h)", local_hexa_id(elem_id)); /* macro */ break; } } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); #endif } #ifdef ELIXIR if(elixir == YES){ #ifdef MAX_LAYER /* must be set before ESIBuildInterface is called */ if(MAX_LAYER <= nparts)single_layer = YES; #endif if(ESIBuildInterface(ESI_GRAPHIC_EDITOR_MASK, 1, &app_nm) != 0){ fprintf(stderr, "Graphic interface error\n"); exit(1); } ESIPopup(); view = ElixirNewView("Metis", "Domain decomposition", "midnightblue", "white", 400, 400); EMAttachView(ESIModel(), view); EVSetViewOrientation(view, VIEW_ORIENT_ISO); EVShowAxes(view, NO); ESIHandleCmd("render ambient 0.1"); EVSetRenderMode(view, WIRE_RENDERING); black = ColorGetPixelFromString("black", &success); white = ColorGetPixelFromString("white", &success); colors[0] = green = ColorGetPixelFromString("green1", &success); colors[1] = red = ColorGetPixelFromString("red1", &success); colors[2] = yellow = ColorGetPixelFromString("yellow1", &success); colors[3] = magenta = ColorGetPixelFromString("magenta1", &success); colors[4] = cyan = ColorGetPixelFromString("cyan1", &success); colors[5] = blue = ColorGetPixelFromString("blue1", &success); colors[6] = orange = ColorGetPixelFromString("orange1", &success); colors[7] = purple = ColorGetPixelFromString("purple1", &success); colors[8] = pink = ColorGetPixelFromString("pink1", &success); #ifdef MORE_COLORS colors[9] = ColorGetPixelFromString("green4", &success); colors[10] = ColorGetPixelFromString("red4", &success); colors[11] = ColorGetPixelFromString("yellow4", &success); colors[12] = ColorGetPixelFromString("magenta4", &success); colors[13] = ColorGetPixelFromString("cyan4", &success); colors[14] = ColorGetPixelFromString("blue4", &success); colors[15] = ColorGetPixelFromString("orange4", &success); colors[16] = ColorGetPixelFromString("purple4", &success); colors[17] = ColorGetPixelFromString("pink4", &success); #endif font = FontGetFontFromString(FONT, &success); if(success == NO)font = FontDefaultFont(); layers = (logic *)calloc(nparts + 1, sizeof(logic)); if(nparts <= NUM_COLORS && single_layer == NO){ for(i = 0; i < nparts; i++){ argn = 0; XtSetArg(args[argn], XtNbackground, colors[i]); argn++; XtSetArg(args[argn], XtNforeground, black); argn++; XtSetValues(set_button[i], args, (Cardinal)argn); XtSetValues(add_button[i], args, (Cardinal)argn); XtSetValues(del_button[i], args, (Cardinal)argn); } } } #endif options[0] = 0; num_flag = 1; if(node_cut == YES){ /* NODE_CUT start */ graph_size = elems; if(static_dd == NO){ if(weight_flag != 0){ if((weight_elem = (idxtype *)calloc(elems, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); for(i = 0; i < elems; i++){ elem_id = i + 1; type = elem_type(elem_id); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem_id); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; weight = entity -> edge_weight; break; case FACE_ELEM: elem = local_face_id(elem_id); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; weight = entity -> face_weight; break; case QUAD_ELEM: elem = local_quad_id(elem_id); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; weight = entity -> quad_weight; break; case TETRA_ELEM: elem = local_tetra_id(elem_id); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; weight = entity -> tetra_weight; break; case PYRAM_ELEM: elem = local_pyram_id(elem_id); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; weight = entity -> pyram_weight; break; case WEDGE_ELEM: elem = local_wedge_id(elem_id); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; weight = entity -> wedge_weight; break; case HEXA_ELEM: elem = local_hexa_id(elem_id); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; weight = entity -> hexa_weight; break; } if(weight == 0){ weight = entity -> elem_weight; if(weight == 0){ switch(type){ case EDGE_ELEM: switch(entity -> type){ case CURVE_ENTITY: sprintf(err_msg, "Element weight specification for edges on %s %ld missing", keyword[CURVE], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for edge on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case FACE_ELEM: switch(entity -> type){ case SURFACE_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[SURFACE], entity -> id); break; case PATCH_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[PATCH], entity -> id); break; case SHELL_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[SHELL], entity -> id); break; default: break; } break; case QUAD_ELEM: switch(entity -> type){ case SURFACE_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[SURFACE], entity -> id); break; case PATCH_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[PATCH], entity -> id); break; case SHELL_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[SHELL], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case TETRA_ELEM: sprintf(err_msg, "Element weight specification for tetras on %s %ld missing", keyword[REGION], entity -> id); break; case PYRAM_ELEM: sprintf(err_msg, "Element weight specification for pyrams on %s %ld missing", keyword[REGION], entity -> id); break; case WEDGE_ELEM: switch(entity -> type){ case REGION_ENTITY: sprintf(err_msg, "Element weight specification for wedges on %s %ld missing", keyword[REGION], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for wedges on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case HEXA_ELEM: switch(entity -> type){ case REGION_ENTITY: sprintf(err_msg, "Element weight specification for hexas on %s %ld missing", keyword[REGION], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for hexas on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; } error_message(err_msg, GENERAL_ERROR); } } weight_elem[i] = weight; } } if(nparts <= 8) METIS_PartGraphRecursive(&graph_size, elem_num_elems, elem_con_elems, weight_elem, NULL, &weight_flag, &num_flag, &nparts, options, &edge_cut, elem_part); else METIS_PartGraphKway(&graph_size, elem_num_elems, elem_con_elems, weight_elem, NULL, &weight_flag, &num_flag, &nparts, options, &edge_cut, elem_part); if(weight_elem != NULL)free(weight_elem); if(min_first == YES){ if((part_elems = (long *)calloc(nparts, sizeof(long))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); if((part_volume = (double *)calloc(nparts, sizeof(double))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); for(i = 0; i < elems; i++){ part_id = elem_part[i]; part_elems[part_id - 1]++; /* this is dangerous because elem_part is of type idxtype; hopefully idxtype is not unsigned */ elem_part[i] = -part_id; elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); volume = 0.0; break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); volume = 0.0; break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); volume = 0.0; break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); volume = calculate_tetra_volume(fe_tetra); break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); volume = 0.0; break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); volume = 0.0; break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); volume = 0.0; break; } part_volume[part_id - 1] += volume; } max_volume = 0.0; for(i = 0; i < nparts; i++){ part_volume[i] /= part_elems[i]; if(part_volume[i]> max_volume)max_volume = part_volume[i]; } max_volume *= 1.0001; for(part = 0; part < nparts; part++){ volume = max_volume; for(j = 0; j < nparts; j++){ if(part_volume[j] < volume){ volume = part_volume[j]; part_id = j + 1; } } part_volume[part_id - 1] = max_volume; for(i = 0; i < elems; i++){ if(-elem_part[i] == part_id)elem_part[i] = part + 1; } } free(part_elems); free(part_volume); } } else{ for(i = 0; i < elems; i++){ elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; break; } elem_part[i] = entity -> partition_id; if(entity -> partition_id == 0) error_message("Unexpected situation", GENERAL_ERROR); } } #ifdef DEBUG fprintf(stdout, "Partitions (elems)1:"); for(i = 0; i < elems; i++)fprintf(stdout, " %ld", (long)(elem_part[i])); fprintf(stdout, "\n"); #endif /* node cut - node_part: positive partition number for nodes inside partition negative number of shared partitions for shared nodes; positive number of partitions + 1 for isolated nodes */ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_num_elems[i + 1] - node_num_elems[i] == 0){ node_part[i] = nparts + 1; /* isolated nodes */ isolated++; continue; } count = 0; elem = node_con_elems[node_num_elems[i]]; part_id = elem_part[elem - 1]; #ifdef MASTER_SLAVE if(master_spec == YES){ /* process shared elements (this is for the case when master node is ordinary shared node) */ if(fe_node -> master == YES){ master = get_master_id(master_list, i + 1); master -> partitions[part_id - 1] = YES; } /* process master-slave relation */ list = fe_node -> entity -> masters; while(list != NULL){ master = (master_rec *)(list -> item); list = list -> next; master -> partitions[part_id - 1] = YES; } } #endif for(j = node_num_elems[i] + 1; j < node_num_elems[i + 1]; j++){ elem = node_con_elems[j] - 1; if(elem_part[elem] != part_id){ if(part_flag[elem_part[elem] - 1] == NO){ count++; part_flag[elem_part[elem] - 1] = YES; #ifdef MASTER_SLAVE if(master_spec == YES){ /* process shared elements (this is for the case when master node is ordinary shared node) */ if(fe_node -> master == YES)master -> partitions[elem_part[elem] - 1] = YES; /* process master-slave relation */ list = fe_node -> entity -> masters; while(list != NULL){ master = (master_rec *)(list -> item); list = list -> next; master -> partitions[elem_part[elem] - 1] = YES; } } #endif } } } if(count == 0) node_part[i] = part_id; else{ node_part[i] = -count - 1; for(j = 0; j < nparts; j++)part_flag[j] = NO; } } #ifdef DEBUG fprintf(stdout, "Partitions (nodes)2:"); for(i = 0; i < nodes; i++)fprintf(stdout, " %ld", (long)(node_part[i])); fprintf(stdout, "\n"); #endif } /* NODE_CUT end */ if(elem_cut == YES){ /* ELEM_CUT start */ if(weight_flag != 0){ if((weight_node = (idxtype *)calloc(nodes, sizeof(idxtype))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); /* 120 is the minimum common denominator of 1/2, 1/3, 1/4, 1/5, 1/6 and 1/8 */ for(i = 0; i < elems; i++){ elem_id = i + 1; type = elem_type(elem_id); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem_id); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; if((weight = entity -> edge_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 2; for(j = 0; j < 2; j++)weight_node[fe_edge -> node[j] -> id - 1] += weight; break; case FACE_ELEM: elem = local_face_id(elem_id); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; if((weight = entity -> face_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 3; for(j = 0; j < 3; j++)weight_node[fe_face -> node[j] -> id - 1] += weight; break; case QUAD_ELEM: elem = local_quad_id(elem_id); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; if((weight = entity -> quad_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 4; for(j = 0; j < 4; j++)weight_node[fe_quad -> node[j] -> id - 1] += weight; break; case TETRA_ELEM: elem = local_tetra_id(elem_id); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; if((weight = entity -> tetra_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 4; for(j = 0; j < 4; j++)weight_node[fe_tetra -> node[j] -> id - 1] += weight; break; case PYRAM_ELEM: elem = local_pyram_id(elem_id); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; if((weight = entity -> pyram_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 5; for(j = 0; j < 5; j++)weight_node[fe_pyram -> node[j] -> id - 1] += weight; break; case WEDGE_ELEM: elem = local_wedge_id(elem_id); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; if((weight = entity -> wedge_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 6; for(j = 0; j < 6; j++)weight_node[fe_wedge -> node[j] -> id - 1] += weight; break; case HEXA_ELEM: elem = local_hexa_id(elem_id); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; if((weight = entity -> hexa_weight) == 0)weight = entity -> elem_weight; weight *= 120 / 8; for(j = 0; j < 8; j++)weight_node[fe_hexa -> node[j] -> id - 1] += weight; break; } if(weight == 0){ switch(type){ case EDGE_ELEM: switch(entity -> type){ case CURVE_ENTITY: sprintf(err_msg, "Element weight specification for edges on %s %ld missing", keyword[CURVE], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for edge on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case FACE_ELEM: switch(entity -> type){ case SURFACE_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[SURFACE], entity -> id); break; case PATCH_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[PATCH], entity -> id); break; case SHELL_ENTITY: sprintf(err_msg, "Element weight specification for faces on %s %ld missing", keyword[SHELL], entity -> id); break; default: break; } break; case QUAD_ELEM: switch(entity -> type){ case SURFACE_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[SURFACE], entity -> id); break; case PATCH_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[PATCH], entity -> id); break; case SHELL_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[SHELL], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for quads on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case TETRA_ELEM: sprintf(err_msg, "Element weight specification for tetras on %s %ld missing", keyword[REGION], entity -> id); break; case PYRAM_ELEM: sprintf(err_msg, "Element weight specification for pyrams on %s %ld missing", keyword[REGION], entity -> id); break; case WEDGE_ELEM: switch(entity -> type){ case REGION_ENTITY: sprintf(err_msg, "Element weight specification for wedges on %s %ld missing", keyword[REGION], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for wedges on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; case HEXA_ELEM: switch(entity -> type){ case REGION_ENTITY: sprintf(err_msg, "Element weight specification for hexas on %s %ld missing", keyword[REGION], entity -> id); break; case INTERFACE_ENTITY: sprintf(err_msg, "Element weight specification for hexas on %s %ld missing", keyword[INTERFACE], entity -> id); break; default: break; } break; } } } } graph_size = nodes; if(nparts <= 8) METIS_PartGraphRecursive(&graph_size, node_num_nodes, node_con_nodes, weight_node, NULL, &weight_flag, &num_flag, &nparts, options, &edge_cut, node_part); else METIS_PartGraphKway(&graph_size, node_num_nodes, node_con_nodes, weight_node, NULL, &weight_flag, &num_flag, &nparts, options, &edge_cut, node_part); if(weight_node != NULL)free(weight_node); #ifdef DEBUG fprintf(stdout, "Partitions (nodes)3:"); for(i = 0; i < nodes; i++)fprintf(stdout, " %ld", (long)(node_part[i])); fprintf(stdout, "\n"); #endif for(i = 0; i < elems; i++){ count = 0; elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); part_id = node_part[fe_edge -> node[0] -> id - 1]; for(j = 1; j < 2; j++){ node = fe_edge -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); part_id = node_part[fe_face -> node[0] -> id - 1]; for(j = 1; j < 3; j++){ node = fe_face -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); part_id = node_part[fe_quad -> node[0] -> id - 1]; for(j = 1; j < 4; j++){ node = fe_quad -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); part_id = node_part[fe_tetra -> node[0] -> id - 1]; for(j = 1; j < 4; j++){ node = fe_tetra -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); part_id = node_part[fe_pyram -> node[0] -> id - 1]; for(j = 1; j < 5; j++){ node = fe_pyram -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); part_id = node_part[fe_wedge -> node[0] -> id - 1]; for(j = 1; j < 6; j++){ node = fe_wedge -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); part_id = node_part[fe_hexa -> node[0] -> id - 1]; for(j = 1; j < 8; j++){ node = fe_hexa -> node[j] -> id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ count++; part_flag[node_part[node] - 1] = YES; } } } break; } if(count == 0) elem_part[i] = part_id; else{ elem_part[i] = -count - 1; for(j = 0; j < nparts; j++)part_flag[j] = NO; } } #ifdef DEBUG fprintf(stdout, "Partitions (elems)4:"); for(i = 0; i < elems; i++)fprintf(stdout, " %ld", (long)(elem_part[i])); fprintf(stdout, "\n"); #endif #ifdef MASTER_SLAVE fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ part_id = node_part[i]; list = fe_node -> entity -> masters; while(list != NULL){ master = (master_rec *)(list -> item); list = list -> next; master -> partitions[part_id - 1] = YES; } } #endif } /* ELEM_CUT end */ } #endif if(renum == YES || interface_last == YES){ if((nd_array = (node_rec *)calloc(nodes, sizeof(node_rec))) == NULL) error_message("Memory allocation error", MEMORY_ERROR); } if(nparts == 1){ /* OOFEM_SEQ start */ if(fprintf(oofem_in_file, "ndofman %ld nelem %ld ncrosssect %d nmat %d nbc %d nic %d nltf %d", nodes, elems, csect, mater, bcond, nic, timef) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ if(barriers != 0){ if(fprintf(oofem_in_file, "nbarrier %d", barriers) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(randgens != 0){ if(fprintf(oofem_in_file, "nrandgen %d", randgens) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(topology_spec == YES){ if(fprintf(oofem_in_file, "topology %s", topology) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(fprintf(oofem_in_file, "\n") < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ if(renum == YES){ for(i = 0; i < nodes; i++){ nd_array[i].id = i + 1; nd_array[i].pos = i; nd_array[i].contact = nd_num_nodes[i + 1] - nd_num_nodes[i]; nd_array[i].connection = &(nd_con_nodes[nd_num_nodes[i]]); } status = renumber_mesh(nodes, nd_array, 0, &old_profile, &new_profile); if(status != 0) error_message("Renumbering error", RENUMBER_ERROR); fprintf(stdout, "Nominal profile: %.0f (old) --> %.0f (new)\n", old_profile, new_profile); fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++)fe_node -> id = nd_array[i].id; } fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(renum == YES) fe_nd = node_array + nd_array[i].pos; else fe_nd = fe_node; if(fprintf(oofem_in_file, "node %ld coords 3 %e %e %e", fe_nd -> id, fe_nd -> x, fe_nd -> y, fe_nd -> z) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ entity = fe_nd -> entity; prop_list = entity -> props[NODE_PROP_KEY]; while(prop_list != NULL){ string = (char *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, "%s", string) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } if(fprintf(oofem_in_file, "\n") < 0)error_message(out_err_msg, FILE_WRITE_ERROR); } /* following block may be done (maybe more elegant) by looping over fe_edge_array, ..., fe_hexa_array */ for(i = 0; i < elems; i++){ elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; elem_type = entity -> edge_type; if(elem_type == NULL)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == CURVE_ENTITY)key = CURVE; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for edges on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 2; j++)nd_id[j] = fe_edge -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 2 %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ if((prop_list = entity -> props[BOUNDARYLOAD_PROP_KEY]) != NULL){ count = get_list_size(prop_list); if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %d", (long)load_id, 1) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if((prop_list = entity -> props[BOUNDARYCODE_PROP_KEY]) != NULL){ count = get_list_size(prop_list); if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %d", 1) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; elem_type = entity -> face_type; if(elem_type == NULL && entity -> faces == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == SURFACE_ENTITY)key = SURFACE; if(entity_type == PATCH_ENTITY)key = PATCH; if(entity_type == SHELL_ENTITY)key = SHELL; sprintf(err_msg, "Element type specification for faces on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 3; j++)nd_id[j] = fe_face -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 3 %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; elem_type = entity -> quad_type; if(elem_type == NULL){ if(entity_type == SURFACE_ENTITY)key = SURFACE; if(entity_type == PATCH_ENTITY)key = PATCH; if(entity_type == SHELL_ENTITY)key = SHELL; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for quads on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 4; j++)nd_id[j] = fe_quad -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; elem_type = entity -> tetra_type; if(elem_type == NULL && entity -> tetras == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ sprintf(err_msg, "Element type specification for tetras in %s %ld missing", keyword[REGION], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 4; j++)nd_id[j] = fe_tetra -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; elem_type = entity -> pyram_type; if(elem_type == NULL && entity -> pyrams == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ sprintf(err_msg, "Element type specification for pyrams in %s %ld missing", keyword[REGION], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 5; j++)nd_id[j] = fe_pyram -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[4], nd_id[4], nd_id[4]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; elem_type = entity -> wedge_type; if(elem_type == NULL && entity -> wedges == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == REGION_ENTITY)key = REGION; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for wedges in %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 6; j++)nd_id[j] = fe_wedge -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[5]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; elem_type = entity -> hexa_type; if(elem_type == NULL){ if(entity_type == REGION_ENTITY)key = REGION; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } for(j = 0; j < 8; j++)nd_id[j] = fe_hexa -> node[j] -> id; if(fprintf(oofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[6], nd_id[7]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ count = 0; for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(oofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(oofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; } prop_list = entity -> props[ELEM_PROP_KEY]; while(prop_list != NULL){ string = (char *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(oofem_in_file, "%s", string) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(fprintf(oofem_in_file, "\n") < 0)error_message(out_err_msg, FILE_WRITE_ERROR); } rewind(control_file); /* skip output file, problem description, analysis, analysis additional, domain, output manager and component size records */ get_next_relevant_record(in_err_msg); get_next_relevant_record(in_err_msg); get_next_relevant_record(in_err_msg); for(i = 0; i < add_recs; i++) get_next_relevant_record(in_err_msg); get_next_relevant_record(in_err_msg); get_next_relevant_record(in_err_msg); get_next_relevant_record(in_err_msg); for(i = 0; i < csect; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM cross section record */ for(i = 0; i < mater; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM material record */ for(i = 0; i < barriers; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM nonlocal barrier record */ for(i = 0; i < randgens; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM random field generator record */ for(i = 0; i < bcond; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM boundary condition record */ for(i = 0; i < nic; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM initial condition record */ for(i = 0; i < timef; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM time function record */ fclose(oofem_in_file); if(domain == YES){ if(strcmp(oofem_in_name, "/dev/null") != 0){ sprintf(oofem_domain_name, "%s.domain", oofem_in_name); if((oofem_in_file = fopen(oofem_in_name, "r")) == NULL){ sprintf(err_msg, "File %s opening error", oofem_in_name); error_message(err_msg, FILE_OPEN_ERROR); } if((oofem_domain_file = fopen(oofem_domain_name, "w")) == NULL){ sprintf(err_msg, "File %s opening error", oofem_domain_name); error_message(err_msg, FILE_OPEN_ERROR); } active_in_file = oofem_in_file; active_out_file = oofem_domain_file; sprintf(in_err_msg, "Unexpected end of oofem in file %s", oofem_in_name); sprintf(out_err_msg, "File %s writing error", oofem_domain_name); get_next_relevant_record(in_err_msg); /* OOFEM output file record */ get_next_relevant_record(in_err_msg); /* OOFEM problem description record */ get_next_relevant_record(in_err_msg); /* OOFEM analysis type record */ for(i = 0; i < add_recs; i++) get_next_relevant_record(in_err_msg); /* OOFEM analysis additional records */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM domain record */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM output manager record */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM number record */ for(i = 0; i < nodes; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM node record */ for(i = 0; i < elems; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM elem record */ for(i = 0; i < csect; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM csect record */ for(i = 0; i < mater; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM mater record */ for(i = 0; i < barriers; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM nonlocal barrier record */ for(i = 0; i < randgens; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM random field generator record */ for(i = 0; i < bcond; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM bcond record */ for(i = 0; i < nic; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM icond record */ for(i = 0; i < timef; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM timef record */ fclose(oofem_in_file); fclose(oofem_domain_file); } } } /* OOFEM_SEQ end */ #ifdef METIS /* OOFEM_PAR start */ else{ /* from this place it is necessary to distinguish between node local id and global glob_id !!! */ for(part = 0; part < nparts; part++){ part_id = part + 1; num_elems = 0; num_nodes = 0; if(node_cut == YES)num_nodes = isolated; /* each partition will posses all isolated nodes */ /* node cut - remote_node: zero for nodes inside partition negative current partition id for shared node positive partition id for nodes outside partition positive current partition id for shared nodes outside partition (the last two are assigned in mark_remote_elems) */ /* note: node ids must be set again because they have been rewritten by zero and local node ids during processing of previous partition; alternatively the code (including subroutines) may be rewritten to work with node glob_id instead of just id */ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ remote_node[i] = 0; fe_node -> id = fe_node -> glob_id; // fe_node -> id = i + 1; if(node_part[i] < 0){ for(j = node_num_elems[i]; j < node_num_elems[i + 1]; j++){ elem = node_con_elems[j] - 1; if(elem_part[elem] == part_id){ remote_node[i] = -part_id; /* shared */ break; } } } } for(i = 0; i < elems; i++){ if(elem_part[i] == part_id) num_elems++; else{ if(elem_part[i] < 0){ /* ELEM_CUT start */ elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); for(j = 0; j < 2; j++){ node = fe_edge -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 2; k++){ node = fe_edge -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); for(j = 0; j < 3; j++){ node = fe_face -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 3; k++){ node = fe_face -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); for(j = 0; j < 4; j++){ node = fe_quad -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 4; k++){ node = fe_quad -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(j = 0; j < 4; j++){ node = fe_tetra -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 4; k++){ node = fe_tetra -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(j = 0; j < 5; j++){ node = fe_pyram -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 5; k++){ node = fe_pyram -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(j = 0; j < 6; j++){ node = fe_wedge -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 6; k++){ node = fe_wedge -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(j = 0; j < 8; j++){ node = fe_hexa -> node[j] -> id - 1; if(node_part[node] == part_id){ num_elems++; remote_elem[i] = -part_id; /* shared */ for(k = 0; k < 8; k++){ node = fe_hexa -> node[k] -> id - 1; if(node_part[node] != part_id)remote_node[node] = node_part[node]; } break; } } break; } } /* ELEM_CUT end */ } } if(node_cut == YES){ /* NODE_CUT start */ /* caution: in this section negative node ids are used; this includes functions: mark_remote_elems mark_remote_elem unmark_nodes */ for(i = 0; i < nodes; i++){ if(node_part[i]> 0)continue; if(remote_node[i]>= 0)continue; for(j = node_num_elems[i]; j < node_num_elems[i + 1]; j++){ elem = node_con_elems[j]; if(elem_part[elem - 1] != part_id)continue; elem_part[elem - 1] = -part_id; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 2; k++){ node_id = abs(fe_edge -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 3; k++){ node_id = abs(fe_face -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 4; k++){ node_id = abs(fe_quad -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 4; k++){ node_id = abs(fe_tetra -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 5; k++){ node_id = abs(fe_pyram -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 6; k++){ node_id = abs(fe_wedge -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 8; k++){ node_id = abs(fe_hexa -> node[k] -> id); if(node_part[node_id - 1] < 0){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; } } for(j = node_num_elems[i]; j < node_num_elems[i + 1]; j++){ elem = node_con_elems[j]; if(elem_part[elem - 1] < 0)elem_part[elem - 1] = part_id; } } } /* NODE_CUT end */ if(elem_cut == YES){ /* ELEM_CUT start */ /* caution: in this section negative node ids are used; this includes functions: mark_remote_elems mark_remote_elem unmark_nodes */ for(i = 0; i < elems; i++){ if(elem_part[i]> 0)continue; if(remote_elem[i]>= 0)continue; elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 2; k++){ node_id = abs(fe_edge -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 3; k++){ node_id = abs(fe_face -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 4; k++){ node_id = abs(fe_quad -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 4; k++){ node_id = abs(fe_tetra -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 5; k++){ node_id = abs(fe_pyram -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 6; k++){ node_id = abs(fe_wedge -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; property_id = entity -> property_id; width = entity -> width; if(width == 0.0)continue; for(k = 0; k < 8; k++){ node_id = abs(fe_hexa -> node[k] -> id); if(node_part[node_id - 1] != part_id){ fe_node = &(node_array[node_id - 1]); mark_remote_elems(fe_node, node_id, part_id, property_id, width * width); unmark_nodes(node_id, part_id, property_id); } } break; } } } /* ELEM_CUT end */ /* generate local numbers; local numbers are not needed if global numbering is required; however, the total number of local nodes and assignment of zero id to nonlocal nodes is still required; local numbering is also necessary for renumbering; however renumbering is currently disabled for global numbering (as it makes no sense) */ if(interface_last == NO){ isolated = 0; fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] == nparts + 1){ /* isolated nodes */ fe_node -> id = ++isolated; continue; } fe_node -> id = 0; if(node_part[i] == part_id) fe_node -> id = ++num_nodes; else{ if(remote_node[i] != 0) fe_node -> id = ++num_nodes; else{ if(fe_node -> master == YES){ #ifdef MASTER_SLAVE master = get_master_id(master_list, i + 1); if(master -> partitions[part] == YES)fe_node -> id = ++num_nodes; #else fe_node -> id = ++num_nodes; #endif } } } } num_renum_nodes = num_nodes; } else{ /* partition nodes */ isolated = 0; fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] == nparts + 1){ /* isolated nodes */ fe_node -> id = ++isolated; continue; } fe_node -> id = 0; if(node_part[i] == part_id){ fe_node -> id = ++num_nodes; if(renum == NO)nd_array[fe_node -> id - 1].pos = i; } else{ if(remote_node[i] == 0){ if(fe_node -> master == YES){ #ifdef MASTER_SLAVE master = get_master_id(master_list, i + 1); if(master -> partitions[part] == YES)fe_node -> id = ++num_nodes; #else fe_node -> id = ++num_nodes; #endif } } } } num_renum_nodes = num_nodes; /* nd_array needs to be setuped also for nodes not subjected to renumbering in order to be able to reorder the nodes in increasing id order on the output; this was absolutely necessary for older version of OOFEM */ /* interface nodes */ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] != part_id){ if(remote_node[i] < 0){ fe_node -> id = ++num_nodes; nd_array[fe_node -> id - 1].pos = i; } } } /* remote nodes */ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] != part_id){ if(remote_node[i]> 0){ fe_node -> id = ++num_nodes; nd_array[fe_node -> id - 1].pos = i; } } } } if(renum == YES){ /* note: only nodes relevant to processed partition are numbered therefore the connected nodes must be "renumbered" into nd_con_nds array */ /* isolated nodes are added to renumbering to ensure that they are started from 1; (this is guaranteed by the renumbering); alternatively, renumbering may be done without isolated nodes, but in that case it must be ensured, that ids in nd_array are starting from 1 (this is required by renumbering) and that the renumbering is used with the proper number of nodes and with the proper shift */ /* the renumbering was not tested if there are further isolated nodes added as master nodes !!! */ if(interface_last == NO){ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] == part_id || node_part[i] == nparts + 1){ j = fe_node -> id - 1; nd_array[j].id = j + 1; nd_array[j].pos = j; nd_array[j].contact = nd_num_nodes[i + 1] - nd_num_nodes[i]; nd_array[j].connection = &(nd_con_nds[nd_num_nodes[i]]); for(k = nd_num_nodes[i]; k < nd_num_nodes[i + 1]; k++){ con_node = nd_con_nodes[k]; fe_nd = &(node_array[con_node - 1]); nd_con_nds[k] = fe_nd -> id; } } else{ if(remote_node[i] != 0){ j = fe_node -> id - 1; nd_array[j].id = j + 1; nd_array[j].pos = j; nd_array[j].connection = &(nd_con_nds[nd_num_nodes[i]]); /* note: not all connections are relevant !!!; count the number of relevant connections and "renumber" them into nd_con_nds array */ contact = 0; for(k = nd_num_nodes[i]; k < nd_num_nodes[i + 1]; k++){ con_node = nd_con_nodes[k]; fe_nd = &(node_array[con_node - 1]); if(fe_nd -> id != 0) nd_array[j].connection[contact++] = fe_nd -> id; } nd_array[j].contact = contact; } } } } else{ fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(node_part[i] == part_id || node_part[i] == nparts + 1){ j = fe_node -> id - 1; nd_array[j].id = j + 1; nd_array[j].pos = j; nd_array[j].connection = &(nd_con_nds[nd_num_nodes[i]]); /* note: not all connections are relevant !!!; count the number of relevant connections and "renumber" them into nd_con_nds array */ contact = 0; for(k = nd_num_nodes[i]; k < nd_num_nodes[i + 1]; k++){ con_node = nd_con_nodes[k]; fe_nd = &(node_array[con_node - 1]); if(fe_nd -> id <= num_renum_nodes) nd_array[j].connection[contact++] = fe_nd -> id; } nd_array[j].contact = contact; } } } #ifdef DEBUG fprintf(stderr, "Partition %d:\n", part_id); for(i = 0; i < num_renum_nodes; i++){ fprintf(stderr, "node %ld: %ld:", nd_array[i].id, nd_array[i].contact); for(j = 0; j < nd_array[i].contact; j++)fprintf(stderr, " %ld", nd_array[i].connection[j]); fprintf(stderr, "\n"); } #endif status = renumber_mesh(num_renum_nodes, nd_array, 0, &old_profile, &new_profile); if(status != 0) error_message("Renumbering error", RENUMBER_ERROR); fprintf(stdout, "Partition %d - nominal profile: %.0f (old) --> %.0f (new)\n", part_id, old_profile, new_profile); fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if((node_id = fe_node -> id) != 0){ if(node_id> num_renum_nodes && interface_last == YES)continue; fe_node -> id = nd_array[node_id - 1].id; nd_array[node_id - 1].id = i; } } for(i = 0; i < num_renum_nodes; i++)nd_array[i].pos = nd_array[nd_array[i].pos].id; } strcpy(poofem_in_name, oofem_in_name); if(strcmp(oofem_in_name, "/dev/null") != 0){ sprintf(suffix, ".%ld", (long)part); strcat(poofem_in_name, suffix); } if((poofem_in_file = fopen(poofem_in_name, "w")) == NULL){ sprintf(err_msg, "File %s opening error", poofem_in_name); error_message(err_msg, FILE_OPEN_ERROR); } active_out_file = poofem_in_file; rewind(control_file); sprintf(in_err_msg, "Unexpected end of control file %s", control_name); sprintf(out_err_msg, "File %s writing error", poofem_in_name); get_next_relevant_record(in_err_msg); if(fprintf(poofem_in_file, "%s.%ld\n", oofem_out_name, (long)part) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM output file record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM problem description record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM analysis type record */ for(i = 0; i < add_recs; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM analysis additional record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM domain record */ read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM output manager record */ get_next_relevant_record(in_err_msg); if(fprintf(poofem_in_file, "ndofman %ld nelem %ld ncrosssect %d nmat %d nbc %d nic %d nltf %d", num_nodes, num_elems, csect, mater, bcond, nic, timef) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ if(barriers != 0){ if(fprintf(poofem_in_file, "nbarrier %d", barriers) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(randgens != 0){ if(fprintf(poofem_in_file, "nrandgen %d", randgens) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(topology_spec == YES){ if(fprintf(poofem_in_file, "topology %s", topology) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ } if(fprintf(poofem_in_file, "\n") < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM component size record */ node_id = 0; fe_node = node_array; for(i = 0; i < nodes; i++, fe_node++){ if(fe_node -> id == 0)continue; ii = i; /* when global node numbering is required it makes no sense to output nodes in renumbered order; but it is done so */ if(renum == YES || interface_last == YES) fe_nd = node_array + (ii = nd_array[node_id++].pos); else fe_nd = fe_node; shared = remote = NO; if(node_part[ii] != part_id && node_part[ii] != nparts + 1){ /* account for isolated nodes */ if(node_part[ii] < 0){ /* shared */ if(-remote_node[ii] == part_id) shared = YES; else{ if(remote_node[ii] == part_id){ remote = shared = YES; /* shared between remote partitions */ } } } else{ if(remote_node[ii] != 0)remote = YES; } if(shared == NO && remote == NO){ if(fe_node -> master == NO)error_message("Unexpected situation", GENERAL_ERROR); } } if(fe_node -> master == YES){ if(remote == YES){ /* remote master node is output as shared */ remote = NO; shared = YES; } else{ if(shared == NO){ #ifdef MASTER_SLAVE /* master node is ouput as local only if not accessed from other partitions */ master = get_master_id(master_list, i + 1); for(j = 0; j < nparts; j++){ if(j == part)continue; if(master -> partitions[j] == YES){ shared = YES; break; } } #else /* master node is ouput as shared */ shared = YES; #endif } } } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO){ if(node_part[ii] == nparts + 1) draw_node(fe_nd, part_id, white, CIRCLE_MARKER, msize); /* isolated node */ else draw_node(fe_nd, part_id, colors[(part_id - 1) % NUM_COLORS], FILLED_CIRCLE_MARKER, msize); } else{ if(shared == YES) draw_node(fe_nd, part_id, white, FILLED_CIRCLE_MARKER, msize); else draw_node(fe_nd, part_id, colors[(remote_node[ii] - 1) % NUM_COLORS], FILLED_CIRCLE_MARKER, msize); } } #endif if(local_num == YES){ if(fprintf(poofem_in_file, "node %ld coords 3 %e %e %e globNum %ld", fe_nd -> id, fe_nd -> x, fe_nd -> y, fe_nd -> z, fe_nd -> glob_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } else{ if(fprintf(poofem_in_file, "node %ld coords 3 %e %e %e", fe_nd -> glob_id, fe_nd -> x, fe_nd -> y, fe_nd -> z) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } /* the ordering (shared + remote -> shared -> remote) is relevant */ if(shared == YES && remote == YES){ #ifdef OUTPUT_REMOTE_PARTITIONS if(fprintf(poofem_in_file, " Remote partitions %ld", (long)(-node_part[ii])) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ for(j = node_num_elems[ii]; j < node_num_elems[ii + 1]; j++){ elem = node_con_elems[j] - 1; if(part_flag[elem_part[elem] - 1] == NO){ part_flag[elem_part[elem] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(elem_part[elem] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } } for(j = 0; j < nparts; j++)part_flag[j] = NO; #else if(fprintf(poofem_in_file, " Null") < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ #endif shared = remote = NO; } if(shared == YES){ if(fe_node -> master == YES){ #ifdef MASTER_SLAVE master = get_master_id(master_list, i + 1); count = 0; for(j = 0; j < nparts; j++){ if(j == part)continue; if(master -> partitions[j] == YES)count++; } if(fprintf(poofem_in_file, " Shared partitions %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ for(j = 0; j < nparts; j++){ if(j == part)continue; if(master -> partitions[j] == YES){ if(fprintf(poofem_in_file, " %ld", j) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } } #else if(fprintf(poofem_in_file, " Shared partitions %ld", (long)(nparts - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ for(j = 0; j < nparts; j++){ if(j == part)continue; if(fprintf(poofem_in_file, " %ld", j) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } #endif } else{ if(fprintf(poofem_in_file, " Shared partitions %ld", (long)(-node_part[ii] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ for(j = node_num_elems[ii]; j < node_num_elems[ii + 1]; j++){ elem = node_con_elems[j] - 1; if(elem_part[elem] != part_id){ if(part_flag[elem_part[elem] - 1] == NO){ part_flag[elem_part[elem] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(elem_part[elem] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } } if(remote == YES){ #ifdef OUTPUT_REMOTE_PARTITIONS if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_node[ii] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ #else if(fprintf(poofem_in_file, " Null") < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ #endif } entity = fe_nd -> entity; prop_list = entity -> props[NODE_PROP_KEY]; while(prop_list != NULL){ string = (char *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, "%s", string) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM node record */ } if(fprintf(poofem_in_file, "\n") < 0)error_message(out_err_msg, FILE_WRITE_ERROR); } part_edges = part_faces = part_quads = part_tetras = part_pyrams = part_wedges = part_hexas = 0; elem_id = 0; for(i = 0; i < elems; i++){ shared = remote = NO; if(elem_part[i] != part_id){ if(elem_part[i] < 0){ if(-remote_elem[i] == part_id)shared = YES; if(remote_elem[i] == part_id){ remote = shared = YES; } } else{ if(remote_elem[i] != 0)remote = YES; } if(shared == NO && remote == NO)continue; } elem_id++; elem = i + 1; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: part_edges++; elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); entity = fe_edge -> entity; elem_type = entity -> edge_type; if(elem_type == NULL)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == CURVE_ENTITY)key = CURVE; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for edges on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_edge(fe_edge, part_id, colors[(part_id - 1) % NUM_COLORS]); else{ if(shared == YES) draw_edge(fe_edge, part_id, white); else draw_edge(fe_edge, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS]); } } #endif if(local_num == YES){ for(j = 0; j < 2; j++)nd_id[j] = fe_edge -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 2 %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 2; j++)nd_id[j] = fe_edge -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 2 %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } /* the ordering (shared + remote -> shared -> remote) is relevant */ if(shared == YES && remote == YES){ node = fe_edge -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 2; j++){ node = fe_edge -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if((prop_list = entity -> props[BOUNDARYLOAD_PROP_KEY]) != NULL){ count = get_list_size(prop_list); if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %d", (long)load_id, 1) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if((prop_list = entity -> props[BOUNDARYCODE_PROP_KEY]) != NULL){ count = get_list_size(prop_list); if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %d", 1) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } break; case FACE_ELEM: part_faces++; elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); entity = fe_face -> entity; elem_type = entity -> face_type; if(elem_type == NULL && entity -> faces == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == SURFACE_ENTITY)key = SURFACE; if(entity_type == PATCH_ENTITY)key = PATCH; if(entity_type == SHELL_ENTITY)key = SHELL; sprintf(err_msg, "Element type specification for faces on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_face(fe_face, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_face(fe_face, part_id, white, black); else draw_face(fe_face, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 3; j++)nd_id[j] = fe_face -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 3 %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 3; j++)nd_id[j] = fe_face -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 3 %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_face -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ node = fe_face -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 3; j++){ if((fe_face -> bflag & (1 << j)) == 0)continue; ent = fe_face -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case QUAD_ELEM: part_quads++; elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); entity = fe_quad -> entity; elem_type = entity -> quad_type; if(elem_type == NULL){ if(entity_type == SURFACE_ENTITY)key = SURFACE; if(entity_type == PATCH_ENTITY)key = PATCH; if(entity_type == SHELL_ENTITY)key = SHELL; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for quads on %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_quad(fe_quad, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_quad(fe_quad, part_id, white, black); else draw_quad(fe_quad, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 4; j++)nd_id[j] = fe_quad -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], nd_id[3], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 4; j++)nd_id[j] = fe_quad -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_quad -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ node = fe_quad -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_quad -> bflag & (1 << j)) == 0)continue; ent = fe_quad -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case TETRA_ELEM: part_tetras++; elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); entity = fe_tetra -> entity; elem_type = entity -> tetra_type; if(elem_type == NULL && entity -> tetras == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ sprintf(err_msg, "Element type specification for tetras in %s %ld missing", keyword[REGION], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_tetra(fe_tetra, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_tetra(fe_tetra, part_id, white, black); else draw_tetra(fe_tetra, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 4; j++)nd_id[j] = fe_tetra -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], nd_id[3], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 4; j++)nd_id[j] = fe_tetra -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 4 %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_tetra -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ node = fe_tetra -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 4; j++){ if((fe_tetra -> bflag & (1 << j)) == 0)continue; ent = fe_tetra -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case PYRAM_ELEM: part_pyrams++; elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); entity = fe_pyram -> entity; elem_type = entity -> pyram_type; if(elem_type == NULL && entity -> pyrams == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ sprintf(err_msg, "Element type specification for pyrams in %s %ld missing", keyword[REGION], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_pyram(fe_pyram, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_pyram(fe_pyram, part_id, white, black); else draw_pyram(fe_pyram, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 5; j++)nd_id[j] = fe_pyram -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[4], nd_id[4], nd_id[4], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 5; j++)nd_id[j] = fe_pyram -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[4], nd_id[4], nd_id[4]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_pyram -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ node = fe_pyram -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_pyram -> bflag & (1 << j)) == 0)continue; ent = fe_pyram -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case WEDGE_ELEM: part_wedges++; elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); entity = fe_wedge -> entity; elem_type = entity -> wedge_type; if(elem_type == NULL && entity -> wedges == entity -> elems)elem_type = entity -> elem_type; /* for compatibility reasons */ if(elem_type == NULL){ if(entity_type == REGION_ENTITY)key = REGION; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for wedges in %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_wedge(fe_wedge, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_wedge(fe_wedge, part_id, white, black); else draw_wedge(fe_wedge, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 6; j++)nd_id[j] = fe_wedge -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[5], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 6; j++)nd_id[j] = fe_wedge -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[5]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_wedge -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ node = fe_wedge -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 5; j++){ if((fe_wedge -> bflag & (1 << j)) == 0)continue; ent = fe_wedge -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; case HEXA_ELEM: part_hexas++; elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); entity = fe_hexa -> entity; elem_type = entity -> hexa_type; if(elem_type == NULL){ if(entity_type == REGION_ENTITY)key = REGION; if(entity_type == INTERFACE_ENTITY)key = INTERFACE; sprintf(err_msg, "Element type specification for hexas in %s %ld missing", keyword[key], entity -> id); error_message(err_msg, GENERAL_ERROR); } #ifdef ELIXIR if(elixir == YES){ if(shared == NO && remote == NO) draw_hexa(fe_hexa, part_id, colors[(part_id - 1) % NUM_COLORS], black); else{ if(shared == YES) draw_hexa(fe_hexa, part_id, white, black); else draw_hexa(fe_hexa, part_id, colors[(remote_elem[i] - 1) % NUM_COLORS], black); } } #endif if(local_num == YES){ for(j = 0; j < 8; j++)nd_id[j] = fe_hexa -> node[j] -> id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld globNum %ld", elem_type, elem_id, nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[6], nd_id[7], (long)(i + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } else{ for(j = 0; j < 8; j++)nd_id[j] = fe_hexa -> node[j] -> glob_id; if(fprintf(poofem_in_file, "%s %ld nodes 8 %ld %ld %ld %ld %ld %ld %ld %ld", elem_type, (long)(i + 1), nd_id[0], nd_id[1], nd_id[2], nd_id[3], nd_id[4], nd_id[5], nd_id[6], nd_id[7]) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(shared == YES && remote == YES){ node = fe_hexa -> node[0] -> glob_id - 1; if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ shared = remote = NO; } if(shared == YES){ if(fprintf(poofem_in_file, " Duplicated partitions %ld", (long)(-elem_part[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 8; j++){ node = fe_hexa -> node[j] -> glob_id - 1; if(node_part[node] != part_id){ if(part_flag[node_part[node] - 1] == NO){ part_flag[node_part[node] - 1] = YES; if(fprintf(poofem_in_file, " %ld", (long)(node_part[node] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } for(j = 0; j < nparts; j++)part_flag[j] = NO; } if(remote == YES){ if(fprintf(poofem_in_file, " Remote partitions 1 %ld", (long)(remote_elem[i] - 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } count = 0; for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if(ent -> props[BOUNDARYLOAD_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYLOAD_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " boundaryLoads %ld", (long)count * 2) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYLOAD_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ load_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld %ld", (long)load_id, (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } count = 0; for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if(ent -> props[BOUNDARYCODE_PROP_KEY] == NULL)continue; count += get_list_size(ent -> props[BOUNDARYCODE_PROP_KEY]); } if(count != 0){ if(fprintf(poofem_in_file, " bsides %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)(j + 1)) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } if(fprintf(poofem_in_file, " bcodes %ld", (long)count) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ for(j = 0; j < 6; j++){ if((fe_hexa -> bflag & (1 << j)) == 0)continue; ent = fe_hexa -> data[j].bound_ent; if((prop_list = ent -> props[BOUNDARYCODE_PROP_KEY]) == NULL)continue; while(prop_list != NULL){ code_id = *(long *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, " %ld", (long)code_id) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } } } break; } prop_list = entity -> props[ELEM_PROP_KEY]; while(prop_list != NULL){ string = (char *)(prop_list -> item); prop_list = prop_list -> next; if(fprintf(poofem_in_file, "%s", string) < 0) error_message(out_err_msg, FILE_WRITE_ERROR); /* OOFEM elem record */ } if(fprintf(poofem_in_file, "\n") < 0)error_message(out_err_msg, FILE_WRITE_ERROR); remote_elem[i] = 0; } fprintf(stdout, "Partition %d - nodes %ld elems %ld (%ld(e) %ld(f) %ld(q) %ld(t) %ld(p) %ld(w) %ld(h))\n", part_id, num_nodes, num_elems, part_edges, part_faces, part_quads, part_tetras, part_pyrams, part_wedges, part_hexas); for(i = 0; i < csect; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM cross section record */ for(i = 0; i < mater; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM material record */ for(i = 0; i < barriers; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM nonlocal barrier record */ for(i = 0; i < randgens; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM random field generator record */ for(i = 0; i < bcond; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM boundary condition record */ for(i = 0; i < nic; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM initial condition record */ for(i = 0; i < timef; i++) read_write_until_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM time function record */ fclose(poofem_in_file); if(domain == YES){ if(strcmp(oofem_in_name, "/dev/null") != 0){ sprintf(poofem_domain_name, "%s.domain.%ld", oofem_in_name, (long)part); if((poofem_in_file = fopen(poofem_in_name, "r")) == NULL){ sprintf(err_msg, "File %s opening error", oofem_in_name); error_message(err_msg, FILE_OPEN_ERROR); } if((poofem_domain_file = fopen(poofem_domain_name, "w")) == NULL){ sprintf(err_msg, "File %s opening error", oofem_domain_name); error_message(err_msg, FILE_OPEN_ERROR); } active_in_file = poofem_in_file; active_out_file = poofem_domain_file; sprintf(in_err_msg, "Unexpected end of oofem in file %s", poofem_in_name); sprintf(out_err_msg, "File %s writing error", poofem_domain_name); get_next_relevant_record(in_err_msg); /* OOFEM output file record */ get_next_relevant_record(in_err_msg); /* OOFEM problem description record */ get_next_relevant_record(in_err_msg); /* OOFEM analysis type record */ for(i = 0; i < add_recs; i++) get_next_relevant_record(in_err_msg); /* OOFEM analysis additional records */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM domain record */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM output manager record */ read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM number record */ for(i = 0; i < num_nodes; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM node record */ for(i = 0; i < num_elems; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM elem record */ for(i = 0; i < csect; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM csect record */ for(i = 0; i < mater; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM mater record */ for(i = 0; i < barriers; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM nonlocal barrier record */ for(i = 0; i < randgens; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM random field generator record */ for(i = 0; i < bcond; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM bcond record */ for(i = 0; i < nic; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM icond record */ for(i = 0; i < timef; i++) read_write_next_relevant_record(in_err_msg, out_err_msg); /* OOFEM timef record */ fclose(poofem_in_file); fclose(poofem_domain_file); active_in_file = control_file; sprintf(in_err_msg, "Unexpected end of control file %s", control_name); } } } } #endif /* OOFEM_PAR end */ fclose(control_file); destroy_entity_list(vertex_list); destroy_entity_list(curve_list); destroy_entity_list(surface_list); destroy_entity_list(patch_list); destroy_entity_list(shell_list); destroy_entity_list(region_list); destroy_entity_list(interface_list); vertex_list = deep_destroy_list(vertex_list); curve_list = deep_destroy_list(curve_list); surface_list = deep_destroy_list(surface_list); patch_list = deep_destroy_list(patch_list); shell_list = deep_destroy_list(shell_list); region_list = deep_destroy_list(region_list); interface_list = deep_destroy_list(interface_list); string_list = deep_destroy_list(string_list); id_list = deep_destroy_list(id_list); #ifdef MASTER_SLAVE if(master_list != NULL){ destroy_master_list(master_list); master_list = deep_destroy_list(master_list); } #endif if(node_array != NULL)free(node_array); if(edge_array != NULL)free(edge_array); if(face_array != NULL)free(face_array); if(quad_array != NULL)free(quad_array); if(tetra_array != NULL)free(tetra_array); if(pyram_array != NULL)free(pyram_array); if(wedge_array != NULL)free(wedge_array); if(hexa_array != NULL)free(hexa_array); if(renum == YES || nparts> 1){ free(node_num_elems); free(node_con_elems); } if(renum == YES){ free(nd_num_nodes); free(nd_con_nodes); if(nparts> 1) free(nd_con_nds); } if(renum == YES || interface_last == YES) free(nd_array); #ifdef METIS if(nparts> 1){ if(node_cut == YES){ free(node_num_nodes); free(node_con_nodes); } if(elem_cut == YES){ free(elem_num_elems); free(elem_con_elems); } free(node_part); free(elem_part); free(remote_node); free(remote_elem); free(part_flag); #ifdef ELIXIR if(elixir == YES){ for(i = 1; i <= nparts; i++){ EVSetLayerOnOff(view, i, YES); layers[i] = YES; } EVFitAllIntoView(view); ERptStatusMessage(1, 1, "Domain decomposition"); ESIEventLoop(YES, NULL); } #endif } #endif return(0); } static list_rec * add_item_to_list_head(list_rec *any_list, void *item) { list_rec *lst = NULL; if(item == NULL)error_message("Null item", GENERAL_ERROR); lst = (list_rec *)malloc(sizeof(list_rec)); if(lst == NULL)error_message("Memory allocation error", MEMORY_ERROR); lst -> item = item; lst -> next = any_list; return(lst); } static list_rec * deep_destroy_list(list_rec *any_list) { list_rec *lst = NULL; while(any_list != NULL){ if(any_list -> item != NULL)free(any_list -> item); any_list = (lst = any_list) -> next; free(lst); } return(NULL); } static list_rec * destroy_list(list_rec *any_list) { list_rec *lst = NULL; while(any_list != NULL){ any_list = (lst = any_list) -> next; free(lst); } return(NULL); } static list_rec * reverse_list(list_rec *any_list) { list_rec *head = NULL, *lst = NULL; if(any_list == NULL)return(NULL); if(any_list -> next == NULL)return(any_list); head = NULL; while((lst = any_list) != NULL){ any_list = any_list -> next; lst -> next = head; head = lst; } return(head); } static long get_list_size(list_rec *any_list) { long count = 0L; while(any_list != NULL){ any_list = any_list -> next; count++; } return(count); } static char * get_next_record(char *err_msg) { char *buf = NULL; if((buf = fgets(line_buffer, BUFFER_SIZE, active_in_file)) == NULL){ if(!feof(active_in_file))error_message("Reading error", FILE_READ_ERROR); if(err_msg == NULL)return(NULL); error_message(err_msg, GENERAL_ERROR); } return(buf); } static char * get_next_relevant_record(char *err_msg) { char *buf = NULL, *character = NULL; do{ if((buf = get_next_record(err_msg)) == NULL)return(NULL); character = line_buffer; while(*character == ' ')character++; }while(*character == '\n' || *character == REMARK); return(buf); } static char * get_first_token(char *buffer) { return(strtok(buffer, SEPARATOR)); } static char * get_next_first_token(char *err_msg) { char *token = NULL, *buf = NULL; while(YES){ if((buf = get_next_relevant_record(err_msg)) == NULL)return(NULL); if((token = strtok(buf, SEPARATOR)) == NULL)continue; break; } return(token); } static char * get_next_token(char *err_msg) { char *token = NULL; if((token = strtok(NULL, SEPARATOR)) == NULL){ if(err_msg == NULL)return(NULL); error_message(err_msg, FILE_READ_ERROR); } if(*token == REMARK)return(NULL); return(token); } static int get_token_key(char *token, char keyword[1][KEY_SIZE], int keynum) { char *t = token; int key; if(KEY_CASE == UPPER_CASE){ while(*t != '0円'){ *t = (char)toupper((int)*t); t++; } } if(KEY_CASE == LOWER_CASE){ while(*t != '0円'){ *t = (char)tolower((int)*t); t++; } } /* do not use strcasecmp (it is not standard) */ for(key = 0; key < keynum; key++){ if(strcmp(token, keyword[key]) == 0) return(key); } return(keynum); } long get_next_int(char *err_msg) { return(get_int_from_token(get_next_token(err_msg))); } double get_next_fpn(char *err_msg) { return(get_fpn_from_token(get_next_token(err_msg))); } long get_int_from_token(char *token) { char *t_ptr = token, *t = token, err_msg[128]; long int_num; int_num = strtol(token, &t_ptr, 10); if(token == t_ptr || *t_ptr != '0円'){ sprintf(err_msg, "Integer number expected (\"%s\" - read)", t); error_message(err_msg, GENERAL_ERROR); } return(int_num); } double get_fpn_from_token(char *token) { char *t_ptr = token, *t = token, err_msg[128]; double fpn_num; fpn_num = strtod(token, &t_ptr); if(token == t_ptr || *t_ptr != '0円'){ sprintf(err_msg, "Floating point number expected (\"%s\" - read)", t); error_message(err_msg, GENERAL_ERROR); } return(fpn_num); } static void write_current_record(char *err_msg) { if(fprintf(active_out_file, "%s", line_buffer) < 0) error_message(err_msg, FILE_WRITE_ERROR); } static void read_write_next_record(char *in_err_msg, char *out_err_msg) { get_next_record(in_err_msg); write_current_record(out_err_msg); } static void read_write_next_relevant_record(char *in_err_msg, char *out_err_msg) { get_next_relevant_record(in_err_msg); write_current_record(out_err_msg); } static void read_write_unrelevant_records(char *in_err_msg, char *out_err_msg) { char *character = NULL; while(YES){ get_next_record(in_err_msg); character = line_buffer; while(*character == ' ')character++; if(*character != '\n' && *character != REMARK)break; write_current_record(out_err_msg); } } static void read_write_until_next_relevant_record(char *in_err_msg, char *out_err_msg) { read_write_unrelevant_records(in_err_msg, out_err_msg); write_current_record(out_err_msg); } static long * get_id(list_rec *id_list, long id) { long *ident = NULL; while(id_list != NULL){ ident = (long *)(id_list -> item); if(*ident == id)return(ident); id_list = id_list -> next; } return(NULL); } static long * create_id(long id) { long *ident = NULL; ident = (long *)malloc(sizeof(long)); if(ident == NULL)error_message("Memory allocation error", MEMORY_ERROR); *ident = id; return(ident); } static master_rec * get_master_id(list_rec *master_list, long id) { master_rec *master = NULL; while(master_list != NULL){ master = (master_rec *)(master_list -> item); if(master -> id == id)return(master); master_list = master_list -> next; } return(NULL); } static master_rec * create_master_id(long id) { master_rec *master = NULL; master = (master_rec *)malloc(sizeof(master_rec)); if(master == NULL)error_message("Memory allocation error", MEMORY_ERROR); master -> id = id; if(nparts != 0){ master -> partitions = (logic *)calloc(nparts, sizeof(logic)); if(master -> partitions == NULL)error_message("Memory allocation error", MEMORY_ERROR); } return(master); } static entity_rec * get_entity_id(list_rec *entity_list, long id) { entity_rec *entity = NULL; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> id == id)return(entity); } return(NULL); } static entity_rec * create_entity_id(long id) { entity_rec *entity = NULL; int i; entity = (entity_rec *)malloc(sizeof(entity_rec)); if(entity == NULL)error_message("Memory allocation error", MEMORY_ERROR); entity -> id = id; entity -> type = 0; entity -> property_id = 0; entity -> selected = NO; entity -> elem_type = NULL; entity -> edge_type = NULL; entity -> face_type = NULL; entity -> quad_type = NULL; entity -> tetra_type = NULL; entity -> pyram_type = NULL; entity -> wedge_type = NULL; entity -> hexa_type = NULL; for(i = 0; i < PROP_KEY_NUM; i++)entity -> props[i] = NULL; entity -> nodes = 0; entity -> elems = 0; entity -> edges = 0; entity -> faces = 0; entity -> quads = 0; entity -> tetras = 0; entity -> pyrams = 0; entity -> wedges = 0; entity -> hexas = 0; entity -> first_node = 0; entity -> first_edge = 0; entity -> first_face = 0; entity -> first_quad = 0; entity -> first_tetra = 0; entity -> first_pyram = 0; entity -> first_wedge = 0; entity -> first_hexa = 0; entity -> elem_weight = 0; entity -> face_weight = 0; entity -> quad_weight = 0; entity -> tetra_weight = 0; entity -> pyram_weight = 0; entity -> wedge_weight = 0; entity -> hexa_weight = 0; entity -> width = 0.0; entity -> partition_id = 0; entity -> boundary = NO; entity -> output = NO; entity -> ngb_ent[0] = NULL; entity -> ngb_ent[1] = NULL; entity -> masters = NULL; return(entity); } static entity_rec * create_missing_entity_id(long id, int entity_type) { entity_rec *entity = NULL; entity = create_entity_id(id); entity -> type = entity_type; switch(entity_type){ case VERTEX_ENTITY: vertex_list = add_item_to_list_head(vertex_list, entity); break; case CURVE_ENTITY: curve_list = add_item_to_list_head(curve_list, entity); break; case SURFACE_ENTITY: surface_list = add_item_to_list_head(surface_list, entity); break; case PATCH_ENTITY: patch_list = add_item_to_list_head(patch_list, entity); break; case SHELL_ENTITY: shell_list = add_item_to_list_head(shell_list, entity); break; case REGION_ENTITY: region_list = add_item_to_list_head(region_list, entity); break; case INTERFACE_ENTITY: interface_list = add_item_to_list_head(interface_list, entity); break; } return(entity); } static void process_entity_list(void) { entity_rec *entity = NULL, *ent = NULL; list_rec *entity_list = NULL, *ent_list = NULL; char *token = NULL, err_msg[128]; long id = 0; switch(last_key = key){ case VERTEX: vertex_select = YES; entity_list = ent_list = vertex_list; break; case CURVE: curve_select = YES; entity_list = ent_list = curve_list; break; case SURFACE: surface_select = YES; entity_list = ent_list = surface_list; break; case PATCH: patch_select = YES; entity_list = ent_list = patch_list; break; case SHELL: shell_select = YES; entity_list = ent_list = shell_list; break; case REGION: region_select = YES; entity_list = ent_list = region_list; break; case INTERFACE: interface_select = YES; entity_list = ent_list = interface_list; break; default: error_message("Unexpected situation", GENERAL_ERROR); } while((token = get_next_token(NULL)) != NULL){ if((key = get_token_key(token, keyword, KEY_NUM)) == ALL){ while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } if((token = get_next_token(NULL)) != NULL){ if((key = get_token_key(token, keyword, KEY_NUM)) != EXCEPT){ sprintf(err_msg, "Invalid or unexpected keyword \"%s\" encountered", token); error_message(err_msg, GENERAL_ERROR); } while((token = get_next_token(NULL)) != NULL){ if((id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } if((entity = get_entity_id(entity_list, id)) == NULL){ fprintf(stderr, "WARNING: %s %ld does not exist ==> created\n", keyword[last_key], id); entity = create_missing_entity_id(id, (int)last_key); /* sprintf(err_msg, "%s %ld does not exist", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); */ } entity -> selected = NO; } if(id == 0){ sprintf(err_msg, "Missing %s id", keyword[last_key]); error_message(err_msg, GENERAL_ERROR); } } return; } if((id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } if((ent = get_entity_id(entity_list, id)) == NULL){ fprintf(stderr, "WARNING: %s %ld does not exist ==> created\n", keyword[last_key], id); ent = create_missing_entity_id(id, (int)last_key); /* sprintf(err_msg, "%s %ld does not exist", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); */ } ent -> selected = YES; } if(id == 0){ sprintf(err_msg, "Missing %s id", keyword[last_key]); error_message(err_msg, GENERAL_ERROR); } } static void process_property_list(void) { entity_rec *entity = NULL; list_rec *ent_list = NULL; char *token = NULL, err_msg[128]; long id = -1; logic sel; last_key = key; while((token = get_next_token(NULL)) != NULL){ if((key = get_token_key(token, keyword, KEY_NUM)) == ALL){ ent_list = vertex_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = curve_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = surface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = patch_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = shell_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = region_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } ent_list = interface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; entity -> selected = YES; } if((token = get_next_token(NULL)) != NULL){ if((key = get_token_key(token, keyword, KEY_NUM)) != EXCEPT){ sprintf(err_msg, "Invalid or unexpected keyword \"%s\" encountered", token); error_message(err_msg, GENERAL_ERROR); } while((token = get_next_token(NULL)) != NULL){ if((id = get_int_from_token(token)) < 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } sel = YES; ent_list = vertex_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = curve_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = surface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = patch_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = shell_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = region_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } ent_list = interface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = NO; } if(sel == YES){ /* I cannot create missing entity because I do not know the property */ sprintf(err_msg, "%s %ld does not exist", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } } if(id == -1){ sprintf(err_msg, "Missing %s id", keyword[last_key]); error_message(err_msg, GENERAL_ERROR); } } return; } if((id = get_int_from_token(token)) < 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } sel = NO; ent_list = vertex_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = curve_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = surface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = patch_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = shell_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = region_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } ent_list = interface_list; while(ent_list != NULL){ entity = (entity_rec *)(ent_list -> item); ent_list = ent_list -> next; if(entity -> property_id == id)entity -> selected = sel = YES; } if(sel == NO){ /* I cannot create missing entity because I do not know the property */ sprintf(err_msg, "%s %ld does not exist", keyword[last_key], id); error_message(err_msg, GENERAL_ERROR); } } if(id == -1){ sprintf(err_msg, "Missing %s id", keyword[last_key]); error_message(err_msg, GENERAL_ERROR); } } static void process_entity_pair_list(void) { entity_rec *entity1 = NULL, *entity2 = NULL; list_rec *entity_list = NULL; int entity_type; long entity1_id, entity2_id, pairs = 0; char *token = NULL, err_msg[128]; last_key = key; while((token = get_next_token(NULL)) != NULL){ key = get_token_key(token, keyword, KEY_NUM); switch(key){ case VERTEX: entity_list = vertex_list; entity_type = VERTEX_ENTITY; break; case CURVE: entity_list = curve_list; entity_type = CURVE_ENTITY; break; case SURFACE: entity_list = surface_list; entity_type = SURFACE_ENTITY; break; case PATCH: entity_list = patch_list; entity_type = PATCH_ENTITY; break; case SHELL: entity_list = shell_list; entity_type = SHELL_ENTITY; break; case REGION: entity_list = region_list; entity_type = REGION_ENTITY; break; case INTERFACE: entity_list = interface_list; entity_type = INTERFACE_ENTITY; break; default: error_message("Invalid entity type encountered", GENERAL_ERROR); } if((token = get_next_token(NULL)) == NULL){ sprintf(err_msg, "First %s specification missing", keyword[key]); error_message(err_msg, GENERAL_ERROR); } if((entity1_id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[key], entity1_id); error_message(err_msg, GENERAL_ERROR); } if((token = get_next_token(NULL)) == NULL){ sprintf(err_msg, "Second %s specification missing", keyword[key]); error_message(err_msg, GENERAL_ERROR); } if((entity2_id = get_int_from_token(token)) <= 0){ sprintf(err_msg, "Invalid %s id (%ld)", keyword[key], entity2_id); error_message(err_msg, GENERAL_ERROR); } if(entity1_id == entity2_id){ sprintf(err_msg, "Identical %s specification", keyword[key]); error_message(err_msg, GENERAL_ERROR); } if((entity1 = get_entity_id(entity_list, entity1_id)) == NULL){ sprintf(err_msg, "%s %ld does not exist", keyword[key], entity1_id); error_message(err_msg, GENERAL_ERROR); } if((entity2 = get_entity_id(entity_list, entity2_id)) == NULL){ sprintf(err_msg, "%s %ld does not exist", keyword[key], entity2_id); error_message(err_msg, GENERAL_ERROR); } if(entity1 -> nodes != entity2 -> nodes){ sprintf(err_msg, "%s %ld is not compatible with %s %ld", keyword[key], entity1_id, keyword[key], entity2_id); error_message(err_msg, GENERAL_ERROR); } if(entity_type != VERTEX_ENTITY){ /* number of elements cannot be compared if any of entity pair was not on output; this must be fixed */ if(entity1 -> elems != entity2 -> elems){ sprintf(err_msg, "%s %ld is not compatible with %s %ld", keyword[key], entity1_id, keyword[key], entity2_id); error_message(err_msg, GENERAL_ERROR); } } switch(last_key){ case MASTERSLAVE: break; default: error_message("Unexpected situation", GENERAL_ERROR); } pairs++; } if(pairs == 0) error_message("Entity type and specification missing", GENERAL_ERROR); } static void deselect_entity_list(list_rec *entity_list) { entity_rec *entity = NULL; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; entity -> selected = NO; } } static void reverse_entity_prop_list(list_rec *entity_list) { entity_rec *entity = NULL; int i; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; for(i = 0; i < PROP_KEY_NUM; i++)entity -> props[i] = reverse_list(entity -> props[i]); } } static void apply_properties(void *item, prop_key prop_key) { if(entity_select == YES){ if(vertex_select == YES)apply_properties_entity_list(vertex_list, item, prop_key); if(curve_select == YES)apply_properties_entity_list(curve_list, item, prop_key); if(surface_select == YES)apply_properties_entity_list(surface_list, item, prop_key); if(patch_select == YES)apply_properties_entity_list(patch_list, item, prop_key); if(shell_select == YES)apply_properties_entity_list(shell_list, item, prop_key); if(region_select == YES)apply_properties_entity_list(region_list, item, prop_key); if(interface_select == YES)apply_properties_entity_list(interface_list, item, prop_key); } } static void apply_properties_entity_list(list_rec *entity_list, void *item, prop_key prop_key) { entity_rec *entity = NULL; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; entity -> props[prop_key] = add_item_to_list_head(entity -> props[prop_key], item); } } static void apply_elem_type(char * elem_type) { if(entity_select == YES){ if(curve_select == YES)apply_elem_type_entity_list(curve_list, elem_type, keyword[CURVE]); if(surface_select == YES)apply_elem_type_entity_list(surface_list, elem_type, keyword[SURFACE]); if(patch_select == YES)apply_elem_type_entity_list(patch_list, elem_type, keyword[PATCH]); if(shell_select == YES)apply_elem_type_entity_list(shell_list, elem_type, keyword[SHELL]); if(region_select == YES)apply_elem_type_entity_list(region_list, elem_type, keyword[REGION]); if(interface_select == YES)apply_elem_type_entity_list(interface_list, elem_type, keyword[INTERFACE]); } } static void apply_elem_type_entity_list(list_rec *entity_list, char *elem_type, char *entity_name) { entity_rec *entity = NULL; char err_msg[128]; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; switch(key){ case ELEMTYPE: if(entity -> elem_type != NULL && entity -> elem_type != elem_type){ sprintf(err_msg, "Duplication of element type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> elem_type = elem_type; break; case EDGETYPE: if(entity -> edge_type != NULL && entity -> edge_type != elem_type){ sprintf(err_msg, "Duplication of edge type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> edge_type = elem_type; break; case TRIATYPE: if(entity -> face_type != NULL && entity -> face_type != elem_type){ sprintf(err_msg, "Duplication of face type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> face_type = elem_type; break; case QUADTYPE: if(entity -> quad_type != NULL && entity -> quad_type != elem_type){ sprintf(err_msg, "Duplication of quad type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> quad_type = elem_type; break; case TETRATYPE: if(entity -> tetra_type != NULL && entity -> tetra_type != elem_type){ sprintf(err_msg, "Duplication of tetra type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> tetra_type = elem_type; break; case HEXATYPE: if(entity -> hexa_type != NULL && entity -> hexa_type != elem_type){ sprintf(err_msg, "Duplication of hexa type specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> hexa_type = elem_type; /* pyrams and wedges are treated as degenerated hexas */ entity -> pyram_type = elem_type; entity -> wedge_type = elem_type; break; default: break; } } } static void apply_width(double width) { apply_width_entity_list(curve_list, width); apply_width_entity_list(surface_list, width); apply_width_entity_list(patch_list, width); apply_width_entity_list(shell_list, width); apply_width_entity_list(region_list, width); apply_width_entity_list(interface_list, width); } static void apply_width_entity_list(list_rec *entity_list, double width) { entity_rec *entity = NULL; char err_msg[128]; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; if(entity -> width != 0.0){ sprintf(err_msg, "Duplication of width specification for %s %ld", keyword[PROPERTY], entity -> property_id); error_message(err_msg, GENERAL_ERROR); } entity -> width = width; } } static void apply_weight(int weight) { apply_weight_entity_list(curve_list, weight, keyword[CURVE]); apply_weight_entity_list(surface_list, weight, keyword[SURFACE]); apply_weight_entity_list(patch_list, weight, keyword[PATCH]); apply_weight_entity_list(shell_list, weight, keyword[SHELL]); apply_weight_entity_list(region_list, weight, keyword[REGION]); apply_weight_entity_list(interface_list, weight, keyword[INTERFACE]); } static void apply_weight_entity_list(list_rec *entity_list, int weight, char *entity_name) { entity_rec *entity = NULL; char err_msg[128]; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; switch(key){ case ELEMWEIGHT: if(entity -> elem_weight != 0 && entity -> elem_weight != weight){ sprintf(err_msg, "Duplication of element weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> elem_weight = weight; break; case EDGEWEIGHT: if(entity -> edge_weight != 0 && entity -> edge_weight != weight){ sprintf(err_msg, "Duplication of edge weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> edge_weight = weight; break; case TRIAWEIGHT: if(entity -> face_weight != 0 && entity -> face_weight != weight){ sprintf(err_msg, "Duplication of face weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> face_weight = weight; break; case QUADWEIGHT: if(entity -> quad_weight != 0 && entity -> quad_weight != weight){ sprintf(err_msg, "Duplication of quad weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> quad_weight = weight; break; case TETRAWEIGHT: if(entity -> tetra_weight != 0 && entity -> tetra_weight != weight){ sprintf(err_msg, "Duplication of tetra weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> tetra_weight = weight; break; case PYRAMWEIGHT: if(entity -> pyram_weight != 0 && entity -> pyram_weight != weight){ sprintf(err_msg, "Duplication of pyram weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> pyram_weight = weight; break; case WEDGEWEIGHT: if(entity -> wedge_weight != 0 && entity -> wedge_weight != weight){ sprintf(err_msg, "Duplication of wedge weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> wedge_weight = weight; break; case HEXAWEIGHT: if(entity -> hexa_weight != 0 && entity -> hexa_weight != weight){ sprintf(err_msg, "Duplication of hexa weight specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> hexa_weight = weight; break; default: break; } } } static void apply_partition(int part_id) { apply_partition_entity_list(curve_list, part_id, keyword[CURVE]); apply_partition_entity_list(surface_list, part_id, keyword[SURFACE]); apply_partition_entity_list(patch_list, part_id, keyword[PATCH]); apply_partition_entity_list(shell_list, part_id, keyword[SHELL]); apply_partition_entity_list(region_list, part_id, keyword[REGION]); apply_partition_entity_list(interface_list, part_id, keyword[INTERFACE]); } static void apply_partition_entity_list(list_rec *entity_list, int part_id, char *entity_name) { entity_rec *entity = NULL; char err_msg[128]; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; if(entity -> partition_id != 0 && entity -> partition_id != part_id){ sprintf(err_msg, "Duplication of partition specification for %s %ld", entity_name, entity -> id); error_message(err_msg, GENERAL_ERROR); } entity -> partition_id = part_id; } } static void apply_master(int master_id) { apply_master_entity_list(vertex_list, master_id, keyword[VERTEX]); apply_master_entity_list(curve_list, master_id, keyword[CURVE]); apply_master_entity_list(surface_list, master_id, keyword[SURFACE]); apply_master_entity_list(patch_list, master_id, keyword[PATCH]); apply_master_entity_list(shell_list, master_id, keyword[SHELL]); apply_master_entity_list(region_list, master_id, keyword[REGION]); } static void apply_master_entity_list(list_rec *entity_list, int master_id, char *entity_name) { entity_rec *entity = NULL; master_rec *master = NULL; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; if(entity -> selected == NO)continue; if((master = get_master_id(master_list, master_id)) == NULL){ master = create_master_id(master_id); master_list = add_item_to_list_head(master_list, (void *)master); } else{ /* prevent repeating master_id; if the master_id is retrived directly from mastermask (which is not the case now) the repetition of master_id can legitimately occur because individual slave dofs may be linked to corresponding dof of the same master node */ if(get_master_id(entity -> masters, master_id) != NULL)continue; } entity -> masters = add_item_to_list_head(entity -> masters, (void *)master); } } static void destroy_entity_list(list_rec *entity_list) { entity_rec *entity = NULL; int i; while(entity_list != NULL){ entity = (entity_rec *)(entity_list -> item); entity_list = entity_list -> next; for(i = 0; i < PROP_KEY_NUM; i++){ if(entity -> props[i] != NULL)entity -> props[i] = destroy_list(entity -> props[i]); } if(entity -> masters != NULL)entity -> masters = destroy_list(entity -> masters); } } static void destroy_master_list(list_rec *master_list) { master_rec *master = NULL; while(master_list != NULL){ master = (master_rec *)(master_list -> item); master_list = master_list -> next; if(master -> partitions != NULL)free(master -> partitions); } } static char * store_string(char *string) { char *str = NULL; str = (char *)malloc((int)strlen(string) + 1); if(str == NULL)error_message("Memory allocation error", MEMORY_ERROR); strcpy(str,string); return(str); } static void exit_error_message(char *message, int exit_code, int line) { fprintf(stderr, "\nt3d2poofem: line %d\n%s\n", line, message); if(exit_code == FILE_READ_ERROR){ fprintf(stderr, "%s\n", line_buffer); } fprintf(stderr, "\n"); exit(exit_code); } #ifdef METIS static void mark_remote_elems(fe_node *node, long node_id, int part_id, long property_id, double width) { int type; long i, j, k, elem, el, nd_id; fe_node *nd = NULL; fe_edge *fe_edge = NULL; fe_face *fe_face = NULL; fe_quad *fe_quad = NULL; fe_tetra *fe_tetra = NULL; fe_pyram *fe_pyram = NULL; fe_wedge *fe_wedge = NULL; fe_hexa *fe_hexa = NULL; double dist; /* for node_cut it is possible to use negative remote_elem as flag for processed elements */ for(i = node_num_elems[node_id - 1]; i < node_num_elems[node_id]; i++){ elem = node_con_elems[i] - 1; if(node_cut == YES){ if(abs(elem_part[elem]) == part_id)continue; } if(elem_cut == YES){ if(elem_part[elem] < 0 && remote_elem[elem] < 0)continue; } elem++; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); if(fe_edge -> entity -> property_id != property_id)continue; for(j = 0; j < 2; j++){ nd_id = fe_edge -> node[j] -> id; if(nd_id < 0)continue; fe_edge -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); if(fe_face -> entity -> property_id != property_id)continue; for(j = 0; j < 3; j++){ nd_id = fe_face -> node[j] -> id; if(nd_id < 0)continue; fe_face -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); if(fe_quad -> entity -> property_id != property_id)continue; for(j = 0; j < 4; j++){ nd_id = fe_quad -> node[j] -> id; if(nd_id < 0)continue; fe_quad -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); if(fe_tetra -> entity -> property_id != property_id)continue; for(j = 0; j < 4; j++){ nd_id = fe_tetra -> node[j] -> id; if(nd_id < 0)continue; fe_tetra -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); if(fe_pyram -> entity -> property_id != property_id)continue; for(j = 0; j < 5; j++){ nd_id = fe_pyram -> node[j] -> id; if(nd_id < 0)continue; fe_pyram -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); if(fe_wedge -> entity -> property_id != property_id)continue; for(j = 0; j < 6; j++){ nd_id = fe_wedge -> node[j] -> id; if(nd_id < 0)continue; fe_wedge -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); if(fe_hexa -> entity -> property_id != property_id)continue; for(j = 0; j < 8; j++){ nd_id = fe_hexa -> node[j] -> id; if(nd_id < 0)continue; fe_hexa -> node[j] -> id = -nd_id; if(nd_id == node_id) dist = 0.0; else{ nd = &(node_array[nd_id - 1]); dist = calculate_distance_square(node, nd); } if(dist < width){ for(k = node_num_elems[nd_id - 1]; k < node_num_elems[nd_id]; k++){ el = node_con_elems[k]; mark_remote_elem(el, part_id); } if(nd_id != node_id)mark_remote_elems(node, nd_id, part_id, property_id, width); } } break; } } } static void mark_remote_elem(long elem_id, int part_id) { int type, i, j; long elem = elem_id - 1; fe_edge *fe_edge = NULL; fe_face *fe_face = NULL; fe_quad *fe_quad = NULL; fe_tetra *fe_tetra = NULL; fe_pyram *fe_pyram = NULL; fe_wedge *fe_wedge = NULL; fe_hexa *fe_hexa = NULL; if(node_cut == YES){ if(abs(elem_part[elem]) == part_id)return; } if(elem_cut == YES){ if(elem_part[elem] < 0 && remote_elem[elem] < 0)return; } if(remote_elem[elem] == elem_part[elem])return; if((remote_elem[elem] = elem_part[elem]) < 0)remote_elem[elem] = part_id; num_elems++; type = elem_type(elem_id); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem_id); /* macro */ fe_edge = &(edge_array[elem - 1]); for(i = 0; i < 2; i++){ j = abs(fe_edge -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case FACE_ELEM: elem = local_face_id(elem_id); /* macro */ fe_face = &(face_array[elem - 1]); for(i = 0; i < 3; i++){ j = abs(fe_face -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case QUAD_ELEM: elem = local_quad_id(elem_id); /* macro */ fe_quad = &(quad_array[elem - 1]); for(i = 0; i < 4; i++){ j = abs(fe_quad -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case TETRA_ELEM: elem = local_tetra_id(elem_id); /* macro */ fe_tetra = &(tetra_array[elem - 1]); for(i = 0; i < 4; i++){ j = abs(fe_tetra -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case PYRAM_ELEM: elem = local_pyram_id(elem_id); /* macro */ fe_pyram = &(pyram_array[elem - 1]); for(i = 0; i < 5; i++){ j = abs(fe_pyram -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case WEDGE_ELEM: elem = local_wedge_id(elem_id); /* macro */ fe_wedge = &(wedge_array[elem - 1]); for(i = 0; i < 6; i++){ j = abs(fe_wedge -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; case HEXA_ELEM: elem = local_hexa_id(elem_id); /* macro */ fe_hexa = &(hexa_array[elem - 1]); for(i = 0; i < 8; i++){ j = abs(fe_hexa -> node[i] -> id) - 1; if(remote_node[j] == 0){ if((remote_node[j] = node_part[j]) < 0)remote_node[j] = part_id; } } break; } } static void unmark_nodes(long node_id, int part_id, long property_id) { int type; long i, j, elem, nd_id; fe_edge *fe_edge = NULL; fe_face *fe_face = NULL; fe_quad *fe_quad = NULL; fe_tetra *fe_tetra = NULL; fe_pyram *fe_pyram = NULL; fe_wedge *fe_wedge = NULL; fe_hexa *fe_hexa = NULL; /* for node_cut it is possible to use negative remote_elem as flag for processed elements */ for(i = node_num_elems[node_id - 1]; i < node_num_elems[node_id]; i++){ elem = node_con_elems[i] - 1; if(node_cut == YES){ if(abs(elem_part[elem]) == part_id)continue; } if(elem_cut == YES){ if(elem_part[elem] < 0 && remote_elem[elem] < 0)continue; } elem++; type = elem_type(elem); /* macro */ switch(type){ case EDGE_ELEM: elem = local_edge_id(elem); /* macro */ fe_edge = &(edge_array[elem - 1]); if(fe_edge -> entity -> property_id != property_id)continue; for(j = 0; j < 2; j++){ nd_id = -(fe_edge -> node[j] -> id); if(nd_id < 0)continue; fe_edge -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case FACE_ELEM: elem = local_face_id(elem); /* macro */ fe_face = &(face_array[elem - 1]); if(fe_face -> entity -> property_id != property_id)continue; for(j = 0; j < 3; j++){ nd_id = -(fe_face -> node[j] -> id); if(nd_id < 0)continue; fe_face -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case QUAD_ELEM: elem = local_quad_id(elem); /* macro */ fe_quad = &(quad_array[elem - 1]); if(fe_quad -> entity -> property_id != property_id)continue; for(j = 0; j < 4; j++){ nd_id = -(fe_quad -> node[j] -> id); if(nd_id < 0)continue; fe_quad -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case TETRA_ELEM: elem = local_tetra_id(elem); /* macro */ fe_tetra = &(tetra_array[elem - 1]); if(fe_tetra -> entity -> property_id != property_id)continue; for(j = 0; j < 4; j++){ nd_id = -(fe_tetra -> node[j] -> id); if(nd_id < 0)continue; fe_tetra -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case PYRAM_ELEM: elem = local_pyram_id(elem); /* macro */ fe_pyram = &(pyram_array[elem - 1]); if(fe_pyram -> entity -> property_id != property_id)continue; for(j = 0; j < 5; j++){ nd_id = -(fe_pyram -> node[j] -> id); if(nd_id < 0)continue; fe_pyram -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case WEDGE_ELEM: elem = local_wedge_id(elem); /* macro */ fe_wedge = &(wedge_array[elem - 1]); if(fe_wedge -> entity -> property_id != property_id)continue; for(j = 0; j < 6; j++){ nd_id = -(fe_wedge -> node[j] -> id); if(nd_id < 0)continue; fe_wedge -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; case HEXA_ELEM: elem = local_hexa_id(elem); /* macro */ fe_hexa = &(hexa_array[elem - 1]); if(fe_hexa -> entity -> property_id != property_id)continue; for(j = 0; j < 8; j++){ nd_id = -(fe_hexa -> node[j] -> id); if(nd_id < 0)continue; fe_hexa -> node[j] -> id = nd_id; if(nd_id != node_id)unmark_nodes(nd_id, part_id, property_id); } break; } } } #endif static double calculate_distance_square(fe_node *node1, fe_node *node2) { double dx, dy, dz; dx = node1 -> x - node2 -> x; dy = node1 -> y - node2 -> y; dz = node1 -> z - node2 -> z; return(dx * dx + dy * dy + dz * dz); } static double calculate_tetra_volume(fe_tetra *tetra) { fe_node *node1 = NULL, *node2 = NULL, *node3 = NULL, *node4 = NULL; double v1x, v1y, v1z; double v2x, v2y, v2z; double v3x, v3y, v3z; double volume; node1 = tetra -> node[0]; node2 = tetra -> node[1]; node3 = tetra -> node[2]; node4 = tetra -> node[3]; v1x = node2 -> x - node1 -> x; v1y = node2 -> y - node1 -> y; v1z = node2 -> z - node1 -> z; v2x = node3 -> x - node1 -> x; v2y = node3 -> y - node1 -> y; v2z = node3 -> z - node1 -> z; v3x = node4 -> x - node1 -> x; v3y = node4 -> y - node1 -> y; v3z = node4 -> z - node1 -> z; volume = (v1y * v2z - v1z * v2y) * v3x + (v1z * v2x - v1x * v2z) * v3y + (v1x * v2y - v1y * v2x) * v3z; return(volume / 6.0); } #ifdef ELIXIR static void draw_node(fe_node *node, int layer, EPixel color, int type, int msize) { WCRec point[1]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; if(single_layer == YES)layer = 0; point[0].x = node -> x; point[0].y = node -> y; point[0].z = node -> z; mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= MTYPE_MASK; mask |= MSIZE_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetMType(type); EASValsSetMSize(msize); if((gr_obj = CreateMarker3D(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); #ifdef DRAW_NODE_NUMBERS draw_number(node -> x, node -> y, node -> z, layer, color, font, node -> glob_id, " "); #endif } static void draw_edge(fe_edge *edge, int layer, EPixel color) { WCRec point[2]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; int i; if(single_layer == YES)layer = 0; for(i = 0; i < 2; i++){ node =edge -> node[i]; point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= STYLE_MASK; mask |= SHRINK_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetLineStyle(SOLID_STYLE); EASValsSetShrink(shrink); if((gr_obj = CreateLine3D(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_face(fe_face *face, int layer, EPixel color, EPixel edge_color) { WCRec point[3]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; int i; if(single_layer == YES)layer = 0; for(i = 0; i < 3; i++){ node = face -> node[i]; point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateTriangle3D(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_quad(fe_quad *quad, int layer, EPixel color, EPixel edge_color) { WCRec point[4]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; int i; if(single_layer == YES)layer = 0; for(i = 0; i < 4; i++){ node = quad -> node[i]; point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateQuad3D(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_tetra(fe_tetra *tetra, int layer, EPixel color, EPixel edge_color) { WCRec point[4]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; int i; if(single_layer == YES)layer = 0; for(i = 0; i < 4; i++){ node = tetra -> node[i]; point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateTetra(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_pyram(fe_pyram *pyram, int layer, EPixel color, EPixel edge_color) { WCRec point[8]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; double x, y, z; int i; if(single_layer == YES)layer = 0; x = y = z = 0.0; for(i = 0; i < 5; i++){ node = pyram -> node[i]; x += point[i].x = node -> x; y += point[i].y = node -> y; z += point[i].z = node -> z; } for(i = 5; i < 8; i++){ point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateHexahedron(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_wedge(fe_wedge *wedge, int layer, EPixel color, EPixel edge_color) { WCRec point[8]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; double x, y, z; int i; if(single_layer == YES)layer = 0; x = y = z = 0.0; for(i = 0; i < 3; i++){ node = wedge -> node[i]; x += point[i].x = node -> x; y += point[i].y = node -> y; z += point[i].z = node -> z; } point[3].x = node -> x; point[3].y = node -> y; point[3].z = node -> z; for(i = 4; i < 7; i++){ node = wedge -> node[i - 1]; x += point[i].x = node -> x; y += point[i].y = node -> y; z += point[i].z = node -> z; } point[7].x = node -> x; point[7].y = node -> y; point[7].z = node -> z; mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateHexahedron(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_hexa(fe_hexa *hexa, int layer, EPixel color, EPixel edge_color) { WCRec point[8]; GraphicObj *gr_obj = NULL; unsigned long mask = 0L; fe_node *node = NULL; int i; if(single_layer == YES)layer = 0; for(i = 0; i < 8; i++){ node = hexa -> node[i]; point[i].x = node -> x; point[i].y = node -> y; point[i].z = node -> z; } mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FILL_MASK; mask |= SHRINK_MASK; mask |= EDGE_COLOR_MASK; mask |= EDGE_FLAG_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFillStyle(FILL_SOLID); EASValsSetShrink(shrink); EASValsSetEdgeColor(edge_color); EASValsSetEdgeFlag(1); if((gr_obj = CreateHexahedron(point)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } static void draw_number(double x, double y, double z, int layer, EPixel color, Font font, long number, char *prefix) { WCRec point; GraphicObj *gr_obj; unsigned long mask = 0L; char string[16]; if(single_layer == YES)layer = 0; point.x = x; point.y = y; point.z = z; sprintf(string, "%s%ld", prefix, number); mask |= LAYER_MASK; mask |= COLOR_MASK; mask |= FONT_MASK; EASValsSetLayer(layer); EASValsSetColor(color); EASValsSetFontId(font); if((gr_obj = CreateAnnText3D(&point, string)) == NULL){ ERptErrMessage(ELIXIR_ERROR_CLASS, 2, "Failure of graphics creation", ERROR_GRADE); exit(ESISetExitCode(2)); } EGWithMaskChangeAttributes(mask, gr_obj); EMAddGraphicsToModel(ESIModel(), gr_obj); } void ESICustomize(Widget parent_pane) { Widget domain_palette, render_palette, view_palette, color_palette; Widget set_palette, add_palette, del_palette; int i; char string[16]; if(single_layer == NO){ ESIAddPalette("Pallette", " Domain ", parent_pane, NULL, 0, &domain_palette); ESIAddButton("Button", " All domains ", commandWidgetClass, domain_palette, NULL, 0, all_domains, NULL); ESIAddPopupDialog(NULL, " Set domain ", "Set domain #", NULL, domain_palette, NULL, 0, set_domain, NULL, ESIDialogValueNumber, NULL); ESIAddPopupDialog(NULL, " Add domain ", "Add domain #", NULL, domain_palette, NULL, 0, add_domain, NULL, ESIDialogValueNumber, NULL); ESIAddPopupDialog(NULL, " Del domain ", "Del domain #", NULL, domain_palette, NULL, 0, del_domain, NULL, ESIDialogValueNumber, NULL); if(nparts <= NUM_COLORS){ ESIAddPalette("Palette", " By color ", domain_palette, NULL, 0, &color_palette); ESIAddPalette("Palette", " Set domain ", color_palette, NULL, 0, &set_palette); ESIAddPalette("Palette", " Add domain ", color_palette, NULL, 0, &add_palette); ESIAddPalette("Palette", " Del domain ", color_palette, NULL, 0, &del_palette); ESIAddButton("label", " Set ", labelWidgetClass, set_palette, NULL, 0, NULL, NULL); ESIAddButton("label", " Add ", labelWidgetClass, add_palette, NULL, 0, NULL, NULL); ESIAddButton("label", " Del ", labelWidgetClass, del_palette, NULL, 0, NULL, NULL); for(i = 0; i < nparts; i++){ sprintf(string, " %d ", i + 1); set_button[i] = ESIAddButton("Button", string, commandWidgetClass, set_palette, NULL, 0, set_nth_domain, (XtPointer)(i + 1)); add_button[i] = ESIAddButton("Button", string, commandWidgetClass, add_palette, NULL, 0, add_nth_domain, (XtPointer)(i + 1)); del_button[i] = ESIAddButton("Button", string, commandWidgetClass, del_palette, NULL, 0, del_nth_domain, (XtPointer)(i + 1)); } } } ESIAddButton("Button", " Toggle shrink ", commandWidgetClass, parent_pane, NULL, 0, toggle_shrink, NULL); ESIAddButton("Button", " Toggle nodes ", commandWidgetClass, parent_pane, NULL, 0, toggle_msize, NULL); ESIAddPalette("Palette", " View ", parent_pane, NULL, 0, &view_palette); ESIAddButton("Button", " New view ", commandWidgetClass, view_palette, NULL, 0, new_view, NULL); ESIAddButton("Button", " Origin ", commandWidgetClass, view_palette, NULL, 0, view_origin, NULL); ESIAddButton("Button", " Fit all ", commandWidgetClass, view_palette, NULL, 0, fit_all, NULL); ESIAddButton("Button", " Redraw ", commandWidgetClass, view_palette, NULL, 0, redraw_view, NULL); ESIAddPalette("Palette", " Render ", view_palette, NULL, 0, &render_palette); ESIAddButton("Button", " Wired view ", commandWidgetClass, render_palette, NULL, 0, render_view, (XtPointer)WIRE_RENDERING); ESIAddButton("Button", " Normal view ", commandWidgetClass, render_palette, NULL, 0, render_view, (XtPointer)NORMAL_RENDERING); ESIAddButton("Button", " Hidden view ", commandWidgetClass, render_palette, NULL, 0, render_view, (XtPointer)FILLED_HIDDEN_RENDERING); ESIAddButton("Button", " Shaded view ", commandWidgetClass, render_palette, NULL, 0, render_view, (XtPointer)CONST_SHADING_RENDERING); } static void new_view(Widget w, XtPointer ptr, XtPointer call_data) { int i; EView *view = NULL; view = ElixirNewView("Metis", "Domain decomposition", "midnightblue", "white", 400, 400); EMAttachView(ESIModel(), view); EMRegenerateGraphics(ESIModel(), view); EVSetViewOrientation(view, VIEW_ORIENT_ISO); EVShowAxes(view, NO); ESIHandleCmd("render ambient 0.1"); EVSetRenderMode(view, WIRE_RENDERING); for(i = 1; i <= nparts; i++){ if(layers[i] == YES)EVSetLayerOnOff(view, i, YES); } EVFitAllIntoView(view); } static void all_domains(Widget w, XtPointer ptr, XtPointer call_data) { int i; EMDispatchToDependentViews(ESIModel(), view_all_domains, NULL); for(i = 1; i <= nparts; i++)layers[i] = YES; } static void set_domain(Widget w, XtPointer ptr, XtPointer call_data) { int i, layer; layer = TypeInGetTokenAsInt(1); if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_set_domain, (caddr_t)layer); for(i = 1; i <= nparts; i++)layers[i] = NO; layers[layer] = YES; } static void add_domain(Widget w, XtPointer ptr, XtPointer call_data) { int layer; layer = TypeInGetTokenAsInt(1); if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_add_domain, (caddr_t)layer); layers[layer] = YES; } static void del_domain(Widget w, XtPointer ptr, XtPointer call_data) { int layer; layer = TypeInGetTokenAsInt(1); if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_del_domain, (caddr_t)layer); layers[layer] = NO; } static void set_nth_domain(Widget w, XtPointer ptr, XtPointer call_data) { int i, layer = (int)ptr; if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_set_domain, (caddr_t)layer); for(i = 1; i <= nparts; i++)layers[i] = NO; layers[layer] = YES; } static void add_nth_domain(Widget w, XtPointer ptr, XtPointer call_data) { int layer = (int)ptr; if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_add_domain, (caddr_t)layer); layers[layer] = YES; } static void del_nth_domain(Widget w, XtPointer ptr, XtPointer call_data) { int layer = (int)ptr; if(layer <= 0 || layer> nparts)return; EMDispatchToDependentViews(ESIModel(), view_del_domain, (caddr_t)layer); layers[layer] = NO; } static int view_all_domains(NODE data, NODE v) { int i; EView *view = (EView *)v; for(i = 1; i <= nparts; i++){ if(EVGetLayerOnOff(view, i) == NO) EVSetLayerOnOff(view, i, YES); } return(1); } static int view_set_domain(NODE data, NODE v) { int i, layer = (int)data; EView *view = (EView *)v; for(i = 1; i <= nparts; i++){ if(i == layer){ if(EVGetLayerOnOff(view, i) == NO) EVSetLayerOnOff(view, i, YES); } else{ if(EVGetLayerOnOff(view, i) == YES) EVSetLayerOnOff(view, i, NO); } } return(1); } static int view_add_domain(NODE data, NODE v) { int layer = (int)data; EView *view = (EView *)v; if(EVGetLayerOnOff(view, layer) == NO) EVSetLayerOnOff(view, layer, YES); return(1); } static int view_del_domain(NODE data, NODE v) { int layer = (int)data; EView *view = (EView *)v; if(EVGetLayerOnOff(view, layer) == YES) EVSetLayerOnOff(view, layer, NO); return(1); } static void toggle_shrink(Widget w, XtPointer ptr, XtPointer call_data) { if(shrink == 1.0) shrink = SHRINK; else shrink = 1.0; EMDispatchToDependentViews(ESIModel(), view_normalize_off, NULL); EMDispatchToGraphicObjects(ESIModel(), shrink_graphics, NULL); EMDispatchToDependentViews(ESIModel(), view_normalize_on, NULL); } static int shrink_graphics(NODE data, NODE gr_obj) { EMEraseGraphics(ESIModel(), (struct GraphicObj *) gr_obj); EASValsSetShrink(shrink); EGWithMaskChangeAttributes(SHRINK_MASK, (struct GraphicObj *) gr_obj); EMDrawGraphics(ESIModel(), (struct GraphicObj *) gr_obj); return(1); } static void toggle_msize(Widget w, XtPointer ptr, XtPointer call_data) { if(msize == 0) msize = MSIZE; else msize = 0; EMDispatchToDependentViews(ESIModel(), view_normalize_off, NULL); EMDispatchToGraphicObjects(ESIModel(), msize_graphics, NULL); EMDispatchToDependentViews(ESIModel(), view_normalize_on, NULL); } static int msize_graphics(NODE data, NODE gr_obj) { EMEraseGraphics(ESIModel(), (struct GraphicObj *) gr_obj); EASValsSetMSize(msize); EGWithMaskChangeAttributes(MSIZE_MASK, (struct GraphicObj *) gr_obj); EMDrawGraphics(ESIModel(), (struct GraphicObj *) gr_obj); return(1); } static int view_normalize_off(NODE data, NODE v) { EView *view = (EView *)v; ERenderingType render_md; int i; render_md = EVGetRenderMode(view); if(render_md == FILLED_HIDDEN_RENDERING || render_md == CONST_SHADING_RENDERING){ for(i = 1; i <= nparts; i++){ if(EVGetLayerOnOff(view, i) == YES) EVSetLayerOnOff(view, i, NO); } } return(1); } static int view_normalize_on(NODE data, NODE v) { EView *view = (EView *)v; ERenderingType render_md; int i; render_md = EVGetRenderMode(view); if(render_md == FILLED_HIDDEN_RENDERING || render_md == CONST_SHADING_RENDERING){ for(i = 1; i <= nparts; i++){ if(EVGetLayerOnOff(view, i) == NO && layers[i] == YES) EVSetLayerOnOff(view, i, YES); } } return(1); } void apply_redraw_view(EView *v_p, caddr_t data, WCRec *p) { /* Doing nothing: redraw is the default of apply_to_view input handler. */ } static void set_render_mode(EView *v_p, caddr_t data, WCRec *p) { EVSetRenderMode(v_p, render_mode); EVSetShadeMode(v_p, shade_mode); } static void uninstall_apply_to_view(EView *v_p, caddr_t data) { EMUninstallHandler(EVGetModel(v_p)); } static void redraw_view(Widget w, XtPointer client_data, XtPointer call_data) { EVSetApplyToViewFunction(apply_redraw_view, NULL, uninstall_apply_to_view); EMPushHandler(ESIModel(), EVApplyToViewHandler, NULL); } static void render_view(Widget w, XtPointer ptr, XtPointer call_data) { render_mode = (ERenderingType) ptr; EVSetApplyToViewFunction(set_render_mode, NULL, uninstall_apply_to_view); EMPushHandler(ESIModel(), EVApplyToViewHandler, NULL); } static void fit_all(Widget w, XtPointer cmdtext_ptr, XtPointer call_data) { ESIHandleCmd("fit"); } static void view_origin(Widget w, XtPointer cmdtext_ptr, XtPointer call_data) { ESIHandleCmd("view origin"); } #endif

AltStyle によって変換されたページ (->オリジナル) /