/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993 Jason I. Gobat and Darren C. Atkinson

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/************************************************************************
 * File:	objects.c						*
 *									*
 * Description:	This file contains the creation and destruction		*
 *		functions for various objects.				*
 *									*
 * History:	V1.0 by Jason Gobat and Darren C. Atkinson		*
 ************************************************************************/

# include <stdio.h>
# include "allocate.h"
# include "error.h"
# include "fe.h"


/************************************************************************
 * Function:	 CreateNode						*
 *									*
 * Parameters:	 number - node number					*
 *									*
 * Return value: new, initialized node					*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateNode creates and initializes a node structure.	*
 *		 The node number is assigned and all pointer fields are	*
 *		 set to NULL.						*
 ************************************************************************/

Node CreateNode (number)
    unsigned number;
{
    Node     node;
    unsigned i;

    if (!(node = AllocNew (struct node)))
	Fatal ("unable to allocate memory for new node");

    node -> number = number;
    node -> force = NULL;
    node -> eq_force = NULL;
    node -> constraint = NULL;
    node -> aux = NULL;

    for (i = 1; i <= 6; i ++)
	node -> dx [i] = 0;

    return node;
}


/************************************************************************
 * Function:	 DestroyNode						*
 *									*
 * Parameters:	 node - node to be destroyed				*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyNode deallocates a node structure.  The		*
 *		 auxillary pointer and equivalent force vector are	*
 *		 deallocated.						*
 ************************************************************************/

void DestroyNode (node)
    Node node;
{
    Deallocate (node -> aux);
    Deallocate (node -> eq_force);
    Deallocate (node);
}


/************************************************************************
 * Function:	 CreateElement						*
 *									*
 * Parameters:	 number - element number				*
 *		 defn	- element definition				*
 *									*
 * Return value: new, initialized element				*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateElement creates and initializes a new element	*
 *		 structure.  The element number and definition are	*
 *		 assigned, the array of node pointers is allocated and	*
 *		 if definition is not NULL, and all other pointer	*
 *		 fields are initialized to NULL.			*
 ************************************************************************/

Element CreateElement (number, defn)
    unsigned   number;
    Definition defn;
{
    unsigned i;
    Element  element;

    if (!(element = AllocNew (struct element)))
	Fatal ("unable to allocate memory for new element");

    element -> node = NULL;

    if (defn && !(element -> node = Allocate (Node, defn -> numnodes)))
	Fatal ("unable to allocate memory for nodes of new element");

    element -> aux = NULL;
    element -> number = number;
    element -> definition = defn;
    UnitOffset (element -> node);

    for (i = 1; i <= defn -> numnodes; i ++)
	element -> node [i] = NULL;

    element -> material = NULL;
    element -> numdistributed = 0;

    for (i = 1; i <= 3; i ++)
	element -> distributed [i] = NULL;

    element -> stress = NULL;
    element -> ninteg = 0;

    return element;
}


/************************************************************************
 * Function:	 DestroyElement						*
 *									*
 * Parameters:	 element - element to be destroyed			*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyElement deallocates an element structure.  The	*
 *		 array of pointers to nodes, the array of stresses, and	*
 *		 the structure pointed to by the auxillary pointer are	*
 *		 deallocated.						*
 ************************************************************************/

void DestroyElement (element)
    Element element;
{
    unsigned	i;

    if (element != NULL) {
        for (i = 1 ; i <= element -> ninteg ; i++) {
	    ZeroOffset (element -> stress [i] -> values);	
	    Deallocate (element -> stress [i] -> values);		
	    Deallocate (element -> stress [i]);
	}
	ZeroOffset (element -> stress);
	Deallocate (element -> stress);
	ZeroOffset (element -> node);
	Deallocate (element -> node);
	Deallocate (element -> aux);
	Deallocate (element);
    }
}


/************************************************************************
 * Function:	 CreateForce						*
 *									*
 * Parameters:	 name - force name					*
 *									*
 * Return value: new, initialized force					*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateForce creates and initializes a force structure.	*
 *		 The name of the force is assigned (not copied) and the	*
 *		 force components are initialized to zero.		*
 ************************************************************************/

Force CreateForce (name)
    char *name;
{
    int   i;
    Force force;

    if (!(force = AllocNew (struct force)))
	Fatal ("unable to allocate memory for new force");

    force -> aux = NULL;
    force -> name = name;
    for (i = 0; i < 7; i ++)
	force -> force [i] = 0;

    return force;
}


/************************************************************************
 * Function:	 DestroyForce						*
 *									*
 * Parameters:	 force - force to be destroyed				*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyForce deallocates a force structure.  The name	*
 *		 and auxillary pointer are also deallocated.		*
 ************************************************************************/

void DestroyForce (force)
    Force force;
{
    if (force != NULL) {
	Deallocate (force -> name);
	Deallocate (force -> aux);
	Deallocate (force);
    }
}


/************************************************************************
 * Function:	 CreateMaterial						*
 *									*
 * Parameters:	 name - material name					*
 *									*
 * Return value: new, initialized material				*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateMaterial creates and initializes a new material	*
 *		 structure.  The name is assigned (not copied) and the	*
 *		 fields are initialized to zero.			*
 ************************************************************************/

Material CreateMaterial (name)
    char *name;
{
    Material material;

    if (!(material = AllocNew (struct material)))
	Fatal ("unable to allocate memory for new material");

    material -> aux   = NULL;
    material -> name  = name;
    material -> E     = 0;
    material -> Ix    = 0;
    material -> Iy    = 0;
    material -> Iz    = 0;
    material -> A     = 0;
    material -> J     = 0;
    material -> G     = 0;
    material -> t     = 0;
    material -> rho   = 0;
    material -> nu    = 0;
    material -> kappa = 0;

    return material;
}


/************************************************************************
 * Function:	 DestroyMaterial					*
 *									*
 * Parameters:	 material - material to be destroyed			*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyMaterial deallocates a material structure.  The	*
 *		 name and auxillary structure are also deallocated.	*
 ************************************************************************/

void DestroyMaterial (material)
    Material material;
{
    if (material != NULL) {
	Deallocate (material -> name);
	Deallocate (material -> aux);
	Deallocate (material);
    }
}


/************************************************************************
 * Function:	 CreateConstraint					*
 *									*
 * Parameters:	 name - constraint name					*
 *									*
 * Return value: new, initialized constraint				*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateConstraint creates and initializes a new		*
 *		 constraint structure.  The name is assigned (not	*
 *		 copied) and the fields are initialized to zero.	*
 ************************************************************************/

Constraint CreateConstraint (name)
    char *name;
{
    int        i;
    Constraint constraint;

    if (!(constraint = AllocNew (struct constraint)))
	Fatal ("unable to allocate memory for new constraint");

    constraint -> aux = NULL;
    constraint -> name = name;
    for (i = 0; i < 7; i ++) {
	constraint -> constraint [i] = 0;
	constraint -> dx [i] = 0;
    }

    return constraint;
}


/************************************************************************
 * Function:	 DestroyConstraint					*
 *									*
 * Parameters:	 constraint - constraint to be destroyed		*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyConstraint deallocates a constraint structure.	*
 *		 The name and auxillary structure are also deallocated.	*
 ************************************************************************/

void DestroyConstraint (constraint)
    Constraint constraint;
{
    if (constraint != NULL) {
	Deallocate (constraint -> name);
	Deallocate (constraint -> aux);
	Deallocate (constraint);
    }
}


/************************************************************************
 * Function:	 CreateDistributed					*
 *									*
 * Parameters:	 name    - distributed name				*
 *		 nvalues - number of values				*
 *									*
 * Return value: new, initialized distributed				*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 CreateDistributed creates and initializes a new	*
 *		 distributed structure.  The name is assigned (not	*
 *		 copied) and the array of values allocated.		*
 ************************************************************************/

Distributed CreateDistributed (name, nvalues)
    char    *name;
    unsigned nvalues;
{
    Distributed distributed;

    if (!(distributed = AllocNew (struct distributed)))
	Fatal ("unable to allocate memory for new distributed");

    distributed -> aux = NULL;
    distributed -> value = NULL;

    if (nvalues && !(distributed -> value = Allocate (Pair, nvalues)))
	Fatal ("unable to allocate memory values for new distributed");

    distributed -> name = name;
    distributed -> nvalues = nvalues;
    UnitOffset (distributed -> value);

    return distributed;
}


/************************************************************************
 * Function:	 DestroyDistributed					*
 *									*
 * Parameters:	 distributed - distributed structure to destroy		*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 none							*
 *									*
 * Description:	 DestroyDistributed deallocates a distributed		*
 *		 structure.  The array of values, name, and auxillary	*
 *		 structure are deallocated.				*
 ************************************************************************/

void DestroyDistributed (distributed)
    Distributed distributed;
{
    if (distributed != NULL) {
	ZeroOffset (distributed -> value);
	Deallocate (distributed -> value);
	Deallocate (distributed -> name);
	Deallocate (distributed -> aux);
	Deallocate (distributed);
    }
}
