function [out,out1,out2]=tetra4(CAM,varargin);

%TETRA4	4-node 12-DOF isoparametric solid element (3P1D)
%
%	As all element functions (see ELEM0), TETRA4 is called by FE_MK for
%	model assembly, FEPLOT for structural deformation visualization, ...
%
%	In an model description matrix a group of TETRA4 elements starts with a
%	header row [Inf  abs('tetra4') 0 ...] followed by element property rows
%       ELT following the format
%	    [n1 ... n4 MatID ProID EltID]
%         with
%          n1 ... n4  identification numbers for the element nodes
%	   MatID  material property identification number
%	   ProID  element property identification number
%
%       PL material property matrix. 
%       3-D isotropic and orthotropic materials are supported.  
%       See M_ELASTIC and FE_MAT
%
%       IL TETRA4 elements do not use element properties.
%
%       Standard tests available with tetra4('testeig') (mat,eig,load) 
%
%	See also help hexa20, hexa8, penta6
% 	         doc  eltfun, elem0

%	E. Balmes, J. Leclere, C. Delforge
%       Copyright (c) 2001-2005 by INRIA and SDTools,All Rights Reserved.
%       Use under OpenFEM trademark.html license and LGPL.txt library license

if comstr(CAM,'cvs')
 out='$Revision: 1.26 $  $Date: 2006/03/30 14:19:04 $'; return;
end
% standard calls with one input argument
if ischar(CAM)

 [CAM,Cam]=comstr(CAM,1);
 % Build Constit, Integ, and Elmap for later integration
 if comstr(Cam,'integinfo')

  %constit integ,elmap                 ID,pl,il
  [out,out1,out2]= ...
   p_solid('buildconstit',[varargin{1};12;4],varargin{2},varargin{3});

 elseif comstr(Cam,'matcall'); [out,out1]=elem0(CAM,varargin{:});
 elseif comstr(Cam,'dofcall');out=elem0('dofcall'); % variable field elements

 elseif comstr(Cam,'call')
   out='[k1,m1]=tetra4(nodeE,elt(cEGI(jElt),:),pointers(:,jElt),integ,constit,elmap);';

 elseif comstr(Cam,'rhscall') % call for load assembly
   out='rhs_of';

 elseif comstr(Cam,'groupinit');out=elem0('groupinitog','tetra4');
 % Here one defines the constants needed for element integration
 elseif comstr(Cam,'constants');

  if nargin<3; p_solid('constsolid','tetra4',[0 0 12 4]',[]);return;
  elseif varargin{2}(end,1)==-9999; % old of_mk_sub.c elements
    out=[];
    out1=varargin{1};out1(4,:)=3;% Tell of_mk('MatrixIntegration') this is 3d
  else;
   [out,i2]=p_solid('constsolid','tetra4',varargin{2:3});
   out1=varargin{1};out1(4,:)=i2; % Tell MatrixIntegration this is 3d 
  end

 elseif comstr(Cam,'node');   out = [1:4];
 elseif  comstr(Cam,'prop');  out = [5 6 7];
 elseif comstr(Cam,'dof');
   out=[1+[1:3]'/100; 2+[1:3]'/100; 3+[1:3]'/100; 4+[1:3]'/100];
 elseif comstr(Cam,'line');    out = [1 2 3 1 4 2 0 3 4];
 elseif comstr(Cam,'patch');   out = [1 3 2;2 4 3;1 4 3;2 4 1];
 elseif  comstr(Cam,'edge');   out = [1 2; 2 3; 3 1; 1 4; 2 4; 3 4];
 elseif  comstr(Cam,'face');   out = [1 3 2; 1 4 3; 1 2 4; 2 3 4];
 elseif  comstr(Cam,'flip');   out=[2 3]; out1=[3 2]; 
 elseif  comstr(Cam,'sci_face'); out = [1 2 4;2 3 4;1 4 3;1 3 2];
 elseif  comstr(Cam,'parent'); out = 'tetra4';

 % Basic matrix test of the element - - - - - - - - - - - - - - - - - -
 elseif  comstr(Cam,'testmat'); [CAM,Cam] = comstr(CAM,5);

   model=femesh('testtetra4');
   [constit,iopt,elmap]=tetra4('integinfo',model.Elt(2,5:6)',model.pl,model.il);

   [k,m]=tetra4(model.Node,model.Elt(2,:),[78 78 0 0 0 0 0 0 0],int32(iopt),constit,elmap);

 iopt(5)=4; constit(2)=.5;
   k1=tetra4(model.Node,model.Elt(2,:),[78 78 0 0 0 0 0 0 0],int32(iopt),constit,elmap);

   out=stack_cell(k,m);
   disp('TestMat passed');

 elseif  comstr(Cam,'test'); [CAM,Cam] = comstr(CAM,5);
 
  [out,out1]=femesh(strcat(['teststruct tetra4' Cam]));

 % Basic tests of the element - - - - - - - - - - - - - - - - - - - - - -
 else sdtw('''%s'' unknown',CAM);  end

return
end % of standard calls with one input argument

% -----------------------------------------------------------------------------
% element matrix assembly - - - - - - - - - - - - - - - - - - - - - - - - - -
node=CAM; 
elt=varargin{1}; 
point=varargin{2};
integ=varargin{3};
constit=varargin{4};
elmap=varargin{5};
if isa(elmap,'int32'); elmap = double(elmap); end


if size(node,2)~=4
 NNode(node(:,1))=1:size(node,1);
 node=node(NNode(elt(1,1:4)),[5:7 1]);
end

if integ(point(6)+7)~=3
 typ=point(5);
 if (typ==0) % mass and stiffness
  [k1,m1]=of_mk('tetra4',int32(point),integ,constit,node);
  k=reshape(k1(elmap),size(elmap,1),size(elmap,2)); m=reshape(m1(elmap),size(elmap,1),size(elmap,2));
  if k(1)<0; error('Reorient elements using feutil(''orient'')'); end
  out=k; out1=m;
 elseif typ==100 
  warning('This standard call should be done in fe_mknl');
  out=of_mk('tetra4',int32(point),varargin{3:4},node,varargin{[5 6 7 8]});
 else
   k1=of_mk('tetra4',int32(point),integ,constit,varargin{[5 6 7 8]});
   k=reshape(k1(elmap),size(elmap,1),size(elmap,2));
   out=k; out1=[];
 end

end

% -----------------------------------------------------------------------------
% -----------------------------------------------------------------------------
% -----------------------------------------------------------------------------
