Extensive updates. The manual should now cover all FEM routines.
authorOrion Lawlor <olawlor@acm.org>
Thu, 11 Dec 2003 21:25:41 +0000 (21:25 +0000)
committerOrion Lawlor <olawlor@acm.org>
Thu, 11 Dec 2003 21:25:41 +0000 (21:25 +0000)
Still need another proofreading pass, though.

doc/fem/Makefile
doc/fem/idxl.tex
doc/fem/manual.tex
doc/fem/mesh.tex

index 82016c80ac762015a4afd607189a4004be006821..c2c3fda186be22559fc403ef70c4ab0d1bd465bc 100644 (file)
@@ -6,6 +6,3 @@ LATEX2HTML=$(L2H) -split 4
 PROJECT_LINK='<a href="http://charm.cs.uiuc.edu/research/fem">FEM Homepage</a><br>'
 
 include ../Makefile.common
-
-index.tex:
-       touch index.tex
index d90ba38d0c812d3aad611fcdd76e3799779d03c6..aca5f52f3c5a656ade1c2dcfa765fec9c9d898a7 100644 (file)
@@ -285,7 +285,7 @@ This section brings together all the pieces of IDXL: Index Lists are used to det
 \function{void IDXL\_Comm\_sendsum(IDXL\_Comm\_t comm,IDXL\_t indices,IDXL\_Layout\_t layout,void *data);}
 \function{SUBROUTINE IDXL\_Comm\_sendsum(comm,indices,layout,data)}
   \args{INTEGER, INTENT(IN)  :: comm,indices,layout}
-  \args{varies, intent(inout) :: data}
+  \args{varies, INTENT(INOUT) :: data}
 
 Sum these \kw{indices} of shared entites across all chunks that share them.
 The user \kw{data} array is interpreted according to the given \kw{layout}.
@@ -325,7 +325,7 @@ by node, you would use:
 \function{void IDXL\_Comm\_sendrecv(IDXL\_Comm\_t comm,IDXL\_t indices,IDXL\_Layout\_t layout,void *data);}
 \function{SUBROUTINE IDXL\_Comm\_sendrecv(comm,indices,layout,data)}
   \args{INTEGER, INTENT(IN)  :: comm,indices,layout}
-  \args{varies, intent(inout) :: data}
+  \args{varies, INTENT(INOUT) :: data}
 
 Send these (typically real) send \kw{indices} and copy in these 
 (typically ghost) receive \kw{indices}.
@@ -408,7 +408,7 @@ will not be copied into until the call to \kw{IDXL\_Comm\_wait}.
 \function{void IDXL\_Comm\_sum(IDXL\_Comm\_t comm,IDXL\_t indices,IDXL\_Layout\_t layout,void *data);}
 \function{SUBROUTINE IDXL\_Comm\_sum(comm,indices,layout,data)}
   \args{INTEGER, INTENT(IN)  :: comm,indices,layout}
-  \args{varies, intent(inout) :: data}
+  \args{varies, INTENT(INOUT) :: data}
 
 When \kw{comm} is finished, add in the values for these receive \kw{indices}, 
 with this \kw{layout}, into this \kw{data} array.
index 7d1543d741d961f269d8fd3a6a0fe4fb3484b921..92d4b25c4f29770912c2161c88483dc9afc61580 100644 (file)
@@ -51,6 +51,7 @@ of spatial dimensions.
 
 
 \subsection{Terminology}
+\label{sec:terminology}
 
 A FEM program manipulates elements and nodes. An \term{element} is a portion of
 the problem domain, also known as a cell, and is typically some simple shape 
@@ -173,13 +174,14 @@ Hence, each chunk's time loop has the structure:
 
 This is exactly the form of the time loop for a \charmpp{} FEM framework
 program.  The framework will accept a serial mesh, partition it, distribute
-the chunks to each processor, allow the user to run their time loop, and
-handle the node-updates.
+the chunks to each processor, then you run your time loop to perform
+analysis and communication.
 
 
-\subsection{Structure of a FEM Framework Program}
+\subsection{Structure of a Classic FEM Framework Program}
 
-A FEM framework program consists of two subroutines: \kw{init()} and \kw{driver()}.
+A classic FEM framework program consists of two subroutines: 
+\kw{init()} and \kw{driver()}.
 \kw{init()} is called by the FEM framework
 only on the first processor -- this routine typically does specialized I/O,
 startup and shutdown tasks.  \kw{driver()} is called for every chunk on every
@@ -187,22 +189,76 @@ processor, and does the main work of the program.  In the language of the
 TCHARM manual, \kw{init()} runs in the serial context, 
 and \kw{driver()} runs in the parallel context.
 
-
 \begin{alltt}
      subroutine init
           read the serial mesh and configuration data
      end subroutine
-
+/* after init, the FEM framework partitions the mesh */
      subroutine driver
           get local mesh chunk
           time loop
                FEM computations
-               update shared node fields
+               communicate boundary conditions
                more FEM computations
           end time loop
      end subroutine
 \end{alltt}
 
+In this mode, the FEM framework sets up a default writing
+mesh during \kw{init()}, partitions the mesh after \kw{init()},
+and sets up the partitioned mesh as the default reading mesh 
+during \kw{driver()}. 
+
+
+\subsection{Structure of an AMPI FEM Framework Program}
+
+In addition to the classic init/driver structure above,
+you can write an FEM framework program using the MPI style.
+This is a more general, more flexible method of running
+the program, but it is more complicated than the classic mode.
+All FEM framework calls are available in either mode.
+
+\begin{alltt}
+   main program
+      MPI_Init
+      FEM_Init(MPI_COMM_WORLD)
+      if (I am master processor)
+         read mesh
+      partition mesh
+      time loop
+          FEM computations
+          communicate boundary conditions
+          more FEM computations
+      end time loop
+   end main program
+\end{alltt}
+
+In this mode, the FEM framework does not set a default
+reading or writing mesh, and does no partitioning;
+so you must use the FEM\_Mesh routines to create and 
+partition your mesh.
+See the AMPI manual for details on how to declare
+the main routine.
+
+The driver() portion of a classic FEM program
+strongly resembles an MPI mode main routine---in fact, a classic
+FEM program can even make MPI calls from its \kw{driver()} 
+routine, because the FEM framework is implemented directly on
+top of MPI.  
+
+There is even a special shell script for collecting
+up the FEM framework source code to build a non-Charm, 
+MPI-only version of the FEM framework; but this version
+is unsupported:
+\begin{alltt}
+  > cd charm
+  > src/libs/ck-libs/fem/make_fem_alone.sh
+  > cd fem_alone
+  > mpicc -c *.C -I. -DFEM_ALONE=1
+  > ar cr libfemalone.a *.o
+\end{alltt}
+
+
 \subsection{Compilation and Execution}
 
 A FEM framework program is a \charmpp\ program, so you must begin by
@@ -235,6 +291,9 @@ After running \kw{init()} normally, the framework partitions the mesh,
 writes the mesh partitions to files, and exits.  As usual, the
 {\tt +vp} $v$ option controls the number of mesh partitions.
 
+This option is only used in the classic mode---MPI-style programs
+are not affected.
+
 
 \item {\tt -read}
 
@@ -253,6 +312,8 @@ a lot of processors.
 
 {\tt -read} can also be useful during debugging or performance tuning, 
 by skipping the (potentially slow) mesh preparation phase.
+This option is only used in the classic mode---MPI-style programs
+are not affected.
 
 
 \item {\tt +tcharm\_trace fem}
@@ -282,21 +343,21 @@ or from whatever TCHARM code executes before the \kw{FEM\_Attach}.
 
 \prototype{FEM\_Num\_partitions}
 \function{int FEM\_Num\_partitions();}
-\function{function integer :: FEM\_Num\_partitions()}
+\function{INTEGER FUNCTION :: FEM\_Num\_partitions()}
 
      Return the number of mesh chunks in the current computation.  Can
      only be called from the driver routine.
 
 \prototype{FEM\_My\_partitions}
 \function{int FEM\_My\_partition();}
-\function{function integer :: FEM\_My\_partition()}
+\function{INTEGER FUNCTION :: FEM\_My\_partition()}
 
      Return the number of the current chunk, from 0 to
      \kw{num\_partitions}-1.  Can only be called from the driver routine.
 
 \prototype{FEM\_Timer}
 \function{double FEM\_Timer();}
-\function{function double precision :: FEM\_Timer()}
+\function{DOUBLE PRECISION FUNCTION :: FEM\_Timer()}
 
      Return the current wall clock time, in seconds.  Resolution is
      machine-dependent, but is at worst 10ms.
@@ -312,7 +373,7 @@ or from whatever TCHARM code executes before the \kw{FEM\_Attach}.
 \prototype{FEM\_Print}
 \function{void FEM\_Print(const char *str);}
 \function{SUBROUTINE FEM\_Print(str)}
-\args{  character*, INTENT(IN) :: str}
+\args{CHARACTER*, INTENT(IN) :: str}
 
      Print the given string, with "[<chunk number>]" printed 
      before the text.  
@@ -351,7 +412,7 @@ reduction over node values), or one of the other routines described below.
 \function{void FEM\_Update\_field(int Fid,void *nodes);}
 \function{SUBROUTINE FEM\_Update\_field(Fid,nodes)}
   \args{INTEGER, INTENT(IN)  :: Fid}
-  \args{varies, intent(inout) :: nodes}
+  \args{varies, INTENT(INOUT) :: nodes}
 
      Combine a field of all shared nodes with the other chunks.  Sums
      the value of the given field across all chunks that share each
@@ -372,7 +433,7 @@ reduction over node values), or one of the other routines described below.
 \function{SUBROUTINE FEM\_Read\_field(Fid,nodes,fName)}
   \args{INTEGER, INTENT(IN)  :: Fid}
   \args{varies, INTENT(OUT) :: nodes}
-  \args{character*, INTENT(IN) :: fName}
+  \args{CHARACTER*, INTENT(IN) :: fName}
 
      Read a field out of the given serial input file.  The serial input
      file is line-oriented ASCII-- each line begins with the global
@@ -468,7 +529,7 @@ It is possible to get values for a chunk's ghost nodes and elements from the nei
 \function{void FEM\_Update\_ghost\_field(int Fid, int elTypeOrMinusOne, void *data);}
 \function{SUBROUTINE FEM\_Update\_ghost\_field(Fid,elTypeOrZero,data)}
   \args{INTEGER, INTENT(IN)  :: Fid,elTypeOrZero}
-  \args{varies, intent(inout) :: data}
+  \args{varies, INTENT(INOUT) :: data}
 
 This has the same requirements and call sequence as \kw{FEM\_Update\_field}, except it applies to ghosts. You specify which type of element to exchange using the elType parameter. Specify -1 (C version) or 0 (fortran version) to exchange node values.  
 
index 32c504a2470e76a05cb3b544e44acd3118a7178f..770b8107901e1bde08c190ae5848f47b2e36ea83 100644 (file)
@@ -143,7 +143,8 @@ Return the default reading mesh.  This routine is valid:
 
 \begin{itemize}
 \item From \kw{driver()}, to return the partitioned mesh.
-\item From the \kw{FEM\_Update\_mesh} routine, to return the assembled mesh.
+\item During your FEM\_Update\_mesh routine, to return the assembled mesh.
+\item Anytime after a call to FEM\_Mesh\_set\_default\_read.
 \end{itemize}
 
 \prototype{FEM\_Mesh\_default\_write}
@@ -155,14 +156,15 @@ Return the default writing mesh.  This routine is valid:
 \begin{itemize}
 \item From \kw{init()}, to change the new serial mesh.
 \item From \kw{driver()}, to change the new partitioned mesh.
-\item From the \kw{FEM\_Update\_mesh} routine, to change the new serial mesh.
+\item During your FEM\_Update\_mesh routine, to change the new serial mesh.
+\item Anytime after a call to FEM\_Mesh\_set\_default\_write.
 \end{itemize}
 
 
 \prototype{FEM\_Mesh\_get\_length}  
 \function{int FEM\_Mesh\_get\_length(int mesh,int entity);}
 \function{INTEGER function :: FEM\_Mesh\_get\_length(mesh,entity)}
-  \args{INTEGER, INTENT(IN) :: mesh,entity) }
+  \args{INTEGER, INTENT(IN) :: mesh,entity }
 
 Return the number of \uw{entity}s that exist in this \uw{mesh}.
 
@@ -262,17 +264,69 @@ user data "tag", for example 13, and:
   \end{alltt}
 
 
-\subsection{Advanced Entity Manipulation}
+\subsection{Entity Inquiry}
 
 \prototype{FEM\_Mesh\_get\_width}  
 \function{int FEM\_Mesh\_get\_width(int mesh,int entity,int attr);}
 \function{INTEGER function :: FEM\_Mesh\_get\_width(mesh,entity,attr)}
-  \args{INTEGER, INTENT(IN) :: mesh,entity,attr) }
+  \args{INTEGER, INTENT(IN) :: mesh,entity,attr }
 
 Return the width of the attribute \uw{attr} of \uw{entity} of \uw{mesh}.
 This is the value previously passed as ``width'' to FEM\_Mesh\_data.
 
 
+\prototype{FEM\_Mesh\_get\_datatype}  
+\function{int FEM\_Mesh\_get\_datatype(int mesh,int entity,int attr);}
+\function{INTEGER function :: FEM\_Mesh\_get\_datatype(mesh,entity,attr)}
+  \args{INTEGER, INTENT(IN) :: mesh,entity,attr }
+
+Return the FEM data type of the attribute \uw{attr} of \uw{entity} of \uw{mesh}.
+This is the value previously passed as ``datatype'' to FEM\_Mesh\_data.
+
+
+\prototype{FEM\_Mesh\_get\_entities}  
+\function{int FEM\_Mesh\_get\_entities(int mesh,int *entities);}
+\function{INTEGER function :: FEM\_Mesh\_get\_entities(mesh,entities)}
+  \args{INTEGER, INTENT(IN) :: mesh}
+  \args{INTEGER, INTENT(OUT) :: entities(:) }
+
+Extract an array of the different entities present in this mesh.
+Returns the number of entity types present.  The \uw{entities}
+array must be big enough to hold all the different entities in
+the mesh.
+
+For example, a simple mesh might have two entity types:
+FEM\_NODE and FEM\_ELEM+1.
+
+
+\prototype{FEM\_Mesh\_get\_attributes}  
+\function{int FEM\_Mesh\_get\_attributes(int mesh,int entity,int *attributes);}
+\function{INTEGER function :: FEM\_Mesh\_get\_attributes(mesh,entity,attributes)}
+  \args{INTEGER, INTENT(IN) :: mesh, entity}
+  \args{INTEGER, INTENT(OUT) :: attributes(:) }
+
+Extract an array of the different attributes of this entity.
+Returns the number of attribute types present.  The \uw{attributes}
+array must be big enough to hold all the attributes.
+
+For example, a simple element might have three attributes:
+FEM\_CONN for node connectivity, FEM\_GLOBALNO for global element
+numbers, and FEM\_DATA+7 for a material type.
+
+\prototype{FEM\_Get\_*\_name}  
+\function{const char *FEM\_Get\_entity\_name(int entity,char *storage);}
+\function{const char *FEM\_Get\_attr\_name(int attr,char *storage);}
+\function{const char *FEM\_Get\_datatype\_name(int datatype,char *storage);}
+
+Return a human-readable name for this FEM entity, attribute, or datatype.
+The \uw{storage} array must point to a buffer of at least 100 characters;
+this array might be used as temporary space to store the returned string.
+
+These routines are only available in C.
+
+
+\subsection{Advanced Entity Manipulation}
+
 \prototype{FEM\_Mesh\_data\_offset}  
 \function{void FEM\_Mesh\_data\_offset(int mesh,int entity,int attr,
         void *data, int first, int length, int datatype,int width,
@@ -308,9 +362,9 @@ expects the structure to be described by an IDXL\_Layout object.
 \label{sec:mesh}
 
 A "mesh" is a collection of nodes and elements 
-bundled together on a single processor.
+knit together in memory, as described in Section~\ref{sec:terminology}.
 Meshes are always referred to by an integer that 
-serves as a handle to the mesh.
+serves as a handle to the local mesh.
 
 This section describes routines to manipulate entire meshes
 at once: this includes calls to create and delete meshes,
@@ -400,7 +454,7 @@ processor \uw{fromRank} needs to pass in a \uw{mesh}; the
 \uw{mesh} value is ignored on other processors.
 
 For example, if rank 0 has a mesh named ``src'', we can 
-partition src for all the processors using:
+partition src for all the processors by executing:
 \begin{alltt}
   m=FEM_Mesh_broadcast(src,0,MPI_COMM_WORLD);
 \end{alltt}
@@ -426,6 +480,40 @@ The new, reassembled mesh is in getting mode.
 This call does not affect \uw{mesh}.
 
 
+\subsection{Mesh Utility}
+
+\prototype{FEM\_Mesh\_is\_get}
+\function{int FEM\_Mesh\_is\_get(int mesh)}
+\function{INTEGER FUNCTION :: FEM\_Mesh\_is\_get(mesh)}
+  \args{INTEGER, INTENT(IN) :: mesh }
+
+Return true if this mesh is in getting mode.
+A getting mesh returns values to FEM\_Mesh\_data.
+
+\prototype{FEM\_Mesh\_is\_set}
+\function{int FEM\_Mesh\_is\_set(int mesh)}
+\function{INTEGER FUNCTION :: FEM\_Mesh\_is\_set(mesh)}
+  \args{INTEGER, INTENT(IN) :: mesh }
+
+Return true if this mesh is in setting mode.
+A setting mesh extracts values from FEM\_Mesh\_data.
+
+
+\prototype{FEM\_Mesh\_become\_get}
+\function{void FEM\_Mesh\_become\_get(int mesh)}
+\function{SUBROUTINE :: FEM\_Mesh\_become\_get(mesh)}
+  \args{INTEGER, INTENT(IN) :: mesh }
+
+Put this mesh in getting mode, so you can read back
+its values.
+
+\prototype{FEM\_Mesh\_become\_set}
+\function{void FEM\_Mesh\_become\_set(int mesh)}
+\function{SUBROUTINE :: FEM\_Mesh\_become\_set(mesh)}
+  \args{INTEGER, INTENT(IN) :: mesh }
+
+Put this mesh in setting mode, so you can set its values.
+
 \prototype{FEM\_Mesh\_print}
 \function{void FEM\_Mesh\_print(int mesh);}
 \function{SUBROUTINE FEM\_Mesh\_print(mesh)}
@@ -435,16 +523,61 @@ Print out a text description of the nodes and elements
 of this mesh.
 
 
-
 \subsection{Advanced Mesh Manipulation}
 
+\prototype{FEM\_Mesh\_pup}
+\function{typedef void (*FEM\_Userdata\_fn)(pup\_er p,void *data);}
+\function{void FEM\_Mesh\_pup(int mesh,int pupTag,FEM\_Userdata\_fn fn,void *data);}
+\function{SUBROUTINE myPupFn(p,data);}
+   \args{INTEGER, INTENT(IN) :: p}
+   \args{TYPE(myType) :: data}
+\function{SUBROUTINE FEM\_Mesh\_pup(mesh,pupTag,myPupFn,data);}
+   \args{INTEGER, INTENT(IN) :: mesh,pupTag}
+   \args{SUBROUTINE :: myPupFn}
+   \args{TYPE(myType) :: data}
+
+Store \uw{data} with this \uw{mesh}.  \uw{data} is a struct or TYPE
+with a pup function \uw{myPupFn}---see the TCharm manual for details 
+on writing a pup function.
+\uw{pupTag} is an integer used to distinguish different pieces of data
+associated with this mesh.
+
+When called on a setting mesh, this routine stores \uw{data};
+when called on a getting mesh, this routine reads out \uw{data}.
+
+\uw{data} will be associated with the mesh itself, not any 
+entity in the mesh.  This makes it useful for storing shared
+data, often simulation constants such as the timestep or material 
+properties.  \uw{data} is made a part of the mesh, and it will be 
+read and written, sent and received, partitioned and assembled
+with the mesh.
+
+
 \prototype{FEM\_Mesh\_send}
   \function{void FEM\_Mesh\_send(int mesh,int toRank,int tag,FEM\_Comm\_t comm\_context);}
-  Send the mesh \uw{mesh} 
+  \function{SUBROUTINE FEM\_Mesh\_send(mesh,toRank,tag,comm)}
+    \args{INTEGER, INTENT(IN) :: mesh,toRank,tag,comm}
+  
+  Send the mesh \uw{mesh} to the processor \uw{toRank}, using
+  the MPI tag \uw{tag} and communicator \uw{comm\_context}.
+  Tags are normally only needed if you plan to mix direct MPI
+  calls with your FEM calls.
+  
+  This call does not affect \uw{mesh}.
   
+
 \prototype{FEM\_Mesh\_recv}
   \function{int FEM\_Mesh\_recv(int fromRank,int tag,FEM\_Comm\_t comm\_context);}
+  \function{INTEGER FUNCTION FEM\_Mesh\_recv(fromRank,tag,comm)}
+    \args{INTEGER, INTENT(IN) :: fromRank,tag,comm}
   
+  Receive a new mesh from the processor \uw{fromRank}, using
+  the MPI tag \uw{tag} and communicator \uw{comm\_context}.
+  You can also use the special values MPI\_ANY\_SOURCE as \uw{fromRank}
+  to receive a mesh from any processor, or use
+  MPI\_ANY\_TAG for \uw{tag} to match any tag.
+
+  The new mesh is returned in getting mode.
 
 \prototype{FEM\_Mesh\_partition}
   \function{void FEM\_Mesh\_partition(int mesh,int nParts,int *destMeshes);}
@@ -456,7 +589,9 @@ Divide \uw{mesh} into \uw{nParts} pieces, and store the pieces
 into the array \uw{destMeshes}. 
 
 The partitioned mesh is returned in getting mode.
+This is a local call; FEM\_Mesh\_broadcast is the collective version.
 This call does not affect the source mesh \uw{mesh}.
+
   
 \prototype{FEM\_Mesh\_assemble}
   \function{int FEM\_Mesh\_assemble(int nParts,const int *srcMeshes);}
@@ -464,9 +599,15 @@ This call does not affect the source mesh \uw{mesh}.
     \args{INTEGER, INTENT(IN) :: nParts, srcMeshes(nParts)}
 
 Assemble the \uw{nParts} meshes listed in \uw{srcMeshes} into
-a single mesh.  
+a single mesh.  Corresponding mesh pieces are matched using 
+the attribute FEM\_GLOBALNO.  Specifically, if the value of 
+the integer index attribute FEM\_GLOBALNO for an entity is $i$,
+the entity will be given the number $i$ in the reassembled mesh.
+If you do not set FEM\_GLOBALNO, the different pieces of the 
+mesh will remain separate---even ``matching'' nodes will not be merged.
 
 The assembled mesh is returned in getting mode.
+This is a local call; FEM\_Mesh\_reduce is the collective version.
 This call does not affect the source meshes.
 
 
@@ -475,7 +616,11 @@ This call does not affect the source meshes.
   \function{SUBROUTINE FEM\_Mesh\_copy\_globalno(src\_mesh,dest\_mesh)}
     \args{INTEGER, INTENT(IN) :: src\_mesh,dest\_mesh}
 
-
+Copy the FEM\_GLOBALNO attribute for all the entity types in 
+\uw{src\_mesh} into all the matching types in \uw{dest\_mesh},
+where the matching types exist.  This call is often used 
+before an FEM\_Mesh\_assemble or FEM\_Mesh\_reduce to synchronize
+global numbers before reassembly.
 
 
 %%%%%%%%%%%%%%%%%%%%%% Ghosts %%%%%%%%%%%%%%%%%%%%%%%%%%