/* * Minimal SWR 0.3 PI (preliminary, only 3D fields in this listing) * (trial version as in FOREST and IEEE Trans. Semi. Manu. vol. 9, * p. 35, 1996.) * * Constructed in 9650 * * Last modification at 9718 after completion of integration of Euclid * as the unstructured tetrahedra gridder. * * Geometry Server * * Terminology definition * * 3D geometry consists of a single collection of volumes, and is the * entire environment under present simulation. * * 3D volume (topological 3D, however it may be degenerated to * topological 2D for handling interface, but the only suggested * usage for this degenerate volume is to provide a consistent * storage mechanism of interface-specific fields (fields that * do not belong to either side of the neighboring volumes such as * interface traps) consists of multiple collections of surfaces * (solid or void dertermined by the composing surface normals). * A volume is of one type of material or interface with homogeneous * representation of physical models. * * ** for convenience, there can be a conceptual 3D sphere class, * which consists of a single collection of enclosing surfaces. * However, this will only be necessary and nonconfusing if the * geometry has complexity higher than 1 (void or hole inside). * Thus, volume <--->>c sphere <--->> surface, * where <--->> denotes one-to-many relations, and * >>c for conditional one to many. A volume will * have many spheres only if it contains voids. * * 3D surface (topological 2D) consists of multiple collections * of edges (solid or void determined by the ordering of edges, * although for 3D geometry, void in surfaces can usually be * "avoided"), and is allowed to take attributes like boundary * and interface conditions. * * ** for convenience, there can be a conceptual 3D loop class, * which consists of a single collection of enclosing edges... * Thus, surface <--->>c boundary <--->> edge * * 3D edge (topological 1D) consists of two bounding points, and * the ordering is not important. * * 3D point (topological 0D) consists of the three coordinate values. * It is suggested that there be no duplicate of points in the * entire scope of the geometry, and a list of "pointers" to * points is provided for constructing other objects. Other instances * of geometry class may allow duplicates for different ownership, but * not suggested. This at least makes the geometry and so on * "topological", and geometrical changes can be persistent by * modifying point coordinates. This also implies the memory free * mechanisms. For two individual geometry instances, there should * not be sharing of any object, including the spatial points. * * Within the server, there is a single definition of the Geometry Class * with limited access functions. * * All coordinates and length are given in microns (um). * Velocities are given in um/s. * Curvature in 1/um. * * Class and function prefix reserved in this PI: * swr: Semiconductor Wafer Representation, for Geometry * class and function names. * ls : level-set boundary representation, as implemented by Z. Hsiau. * ot : oct-tree grid, as implemented in CAMINO by T. Chen. * ut : unstructured tetrahedra grid, as implemented in EUCLID by * N. Golias. * * Procedural interface * Mainly for illustration. For function prototypes in .h, illustrative * variable names need to be removed. All iterators now use MACRO, and * should be commented out. */ swrGeometry* swrGeometryRead(char *fileName); // Zak's simple geometry file acceptable, later on expand to tcl // in CVSwork/forest/Input. Test geometry for 3D necessary // Geometry can be alternatively created from solid modelers, such // as describing a cube, a cylinder or a ball. However, // the solid-modeling input and the boolean functions are provided // through a translator to solid modeler (for us: ACIS or VIP), // instead of burdens of this simple PI. int swrGeometryStore(swrGeometry *, char *fileName); // test cases for consistency of store and read back from files void swrGeometrySetAttribute(swrGeometry *, char *attrName, char *attrValue); // persistent attribute provided for geometry, volume and surface only // material name for volume is suggested -- "material" // Zak's implementation acceptable, simple reorganization char *swrGeometryGetAttribute(swrGeometry *, char *attrName); void swrGeometryRemoveAttribute(swrGeometry *, char *attrName); int swrGeometryAddVolume(swrGeometry *, swrVolume *); // Volume is enlisted in the geometry. If no-duplicate policy // is enforced, the content of Geometry and Volume may be changed. // Volume * remained as a valid pointer. // return SUCCESS or FAIL // ordering unspecified int swrGeometryDeleteVolume(swrGeometry *, swrVolume *); // Volume is detached from geometry, but not freed. Volume * is // still a valid pointer. If Volume does not belong to Geometry, // report FAIL. int swrGeometryNoofVolume(swrGeometry *); // return no. of volumes belonging to Geometry. // Iterators swrForEachVolumeinGeometry(swrGeometry *, swrVolume *) swrForEachSurfaceinVolume(swrVolume *, swrSurface *) swrForEachEdgeinSurface(swrSurface *, swrEdge *) swrForEachPointinEdge(swrEdge *, swrPoint *) // questions here: always hierarchical access??? Calls like // ForEachPointinGeometry() can be provided... // First implementation: assume interfaces always match and just search // for the same geometrical points in each volume and unify the pointers. // The geometrical points may need lists of volumes, surfaces, and // edges associated with it, or an efficient method to provide // this list. int swrGeometryValid(swrGeometry *); // check for region overlap, disconnected regions, loops, etc. void swrGeometryFree(swrGeometry *); // Free every volume and field belonged to it. Free the // geometrical points associated with it. This is the only // way to free geometrical points. VolumeFree() only free // the pointer structures. // The real meat of a geometry SERVER: functionalities // int lsGeometryMove(swrGeometry *, double time); // Move according to PointSetVelocity(), ls for Z. Hsiau's level set // assume point velocity set correctly // return SUCCESS or FAIL // notice that even the "triple" point has been assigned a single // velocity, the boundary move will still be correct in level set. double lsGeometryMaxDt(swrGeometry *, double timeLimit); // time limit to resolve sharp corners accurately int lsGeometrySmooth(swrGeometry *, double curvatureThreshold); // in 2D, the concept is clear. Delete intermediate points during // cell marching if curvature below threshold. In 3D, the oct-tree // is searched upwards until the curvatureThreshold is reached. // Extract the surface triangles or quad from the largest cube. // A new extracted geometry will replace the original geometry // (cannot go back). Curvature given in 1/um. int lsGeometryAdpat(swrGeometry *, int level); // set the minimum adaptation level for quad/oct tree and replace // geometry with the newly extracted surfaces (level set functions // will be interpolated). // PI for volume void swrVolumeSetAttribute(swrVolume *, char *attrName, char *attrValue); char *swrVolumeGetAttribute(swrVolume *, char *attrName); void swrVolumeRemoveAttribute(swrVolume *, char *attrName); int swrVolumeIndex(swrGeometry *, swrVolume *); // return a unique volume index if Volume * belongs to Geometry * // return -1 if Volume * not belonging to Geometry *. // this is useful in speeding up the construction of fields on volume. // or write out Suprem-like structure files. int swrVolumeNoofSurface(swrVolume *); int swrVolumeForm(swrVolume *, int numSurface, swrSurface **surfacePtr); // ordering not important... Inside and outside are determined by // surface normal, not the ordering of surfaces. int swrVolumeDegenerate(swrVolume *); // check internal flags if the volume is degenerate (interface). // the surface iterators will still return the surface elements, just // not enclosing. void swrVolumeFree(swrVolume *); // Free the pointer structures, but not the geometrical points. // Optional in first release. // No free function provided for surface, edge and point. // PI for surface // void swrSurfaceSetAttribute(swrSurface *, char *attrName, char *attrValue); char *swrSurfaceGetAttribute(swrSurface *, char *attrName); void swrSurfaceRemoveAttribute(swrSurface *, char *attrName); int swrSurfaceNoofEdges(swrSurface *); int swrSurfaceForm(swrSurface *, int numEdge, swrEdge **edgePtr); // Construct surface from a collection of edges // ordering important to determine inside and outside of surface, // and also surface normal. In 3D, right-hand rule is used // (thumb is the normal and "inside") // return SUCCESS or FAIL // PI for edge swrPoint *swrEdgeStartPoint(swrEdge *); swrPoint *swrEdgeEndPoint(swrEdge *); int swrEdgeForm(swrEdge *, swrPoint *startPoint, swrPoint *endPoint); // Construct edge from two points // return SUCCESS or FAIL // PI for Point double swrPointCoord(Point *, int axis); // 1 for x, 2 for y, and 3 for z. Possible extension to // cylindrical and spherical coordinates 4, 5, 6, etc. double swrPointVelocity(swrPoint *, int axis); void swrPointSetCoord(swrPoint *, int axis, double val); void swrPointSetVelocity(swrPoint *, int axis, double val); /* ----------------------------------------------------------- */ /* * Grid Server (temporarily we will not have a surface mesher). * Geometry will be a "surface mesh" if extracted from gridder. * The only missing functionality is to support boundary element methods * for arbitary fields on surface mesh. * "ot" denotes oct-tree (CAMINO) grid and "ut" denotes unstructured * tetrahedra grid (EUCLID) as examples. */ otGrid *otGridGenerate(char* fileForLevelMap, swrGeometry * ); utGrid *utGridGenerate(swrGeometry * ); // not presently implemented utGrid *utGridGenerateFromCubes(int num_cube, cube_input*); // class cube_input // { // public: // double x1, y1, z1; // coordinate of the first point // double x2, y2, z2; // coordinate of the second point // double max_length; // // the max edge length of elements in the cube // int volumeIndex; // the volume to which the cube belong // }; utGrid *utGridfromCAMINO(otGrid *); // not available in Euclid.a // need to compile and link separately swrGeometry *otGeometryGenerate(otGrid *); swrGeometry *utGeometryGenerate(utGrid *); int otGridStore(otGrid *, int numFileNames, char **fileNames); // Now HDF-Vset is not imposed, but suggested. Later on // HDF-Vset can be used as partial communication purposes. int utGridStore(utGrid *, int numFileNames, char **fileNames); // not presently implemented otGrid* otGridRead(int numFileNames, char **fileNames); utGrid* utGridRead(int numFileNames, char **fileNames); // not presently implemented int otGridValid(otGrid *); // presently just some simple checks... A signature of class // (optionally with version number) is suggested for easy distinction. int utGridValid(utGrid *); // not presently implemented int otGridAdapt(otGrid *, int adaptFlag, char *elementSolutionName); // ??? adaptFlag definition // adaptFlag: 0: elementSolution is normalized, negative: unrefine, // 0: no change, positive: refine // adaptFlag: 1: whatever is now in CAMINO... // adaptFlag: 2: refinement only... // return SUCCESS or FAIL int utGridAdapt(utGrid *, int adaptFlag, char *elementSolutionName, double threshold); // adaptFlag is not used // return SUCCESS or FAIL int utGridMove(utGrid *, double time, char *xvelName, char *yvelName, char *zvelName); // not presently implemented double utGridMaxDt(utGrid, char *xvelName, char *yvelName, char *zvelName, double maxTimeAllowed); // not presently implemented int utGridConstruct(utGrid *, int numPoints, double *xCoord, double *yCoord, double *zCoord, int numElements, int* connectivity); // not implemented int utGridNoOfVolume(utGrid *); int utGridAddSolution(utGrid *, char *solutionName, int solutionType, int interpolationType, int volumeIndex); int otGridAddSolution(otGrid *, char *solutionName, int solutionType, int interpolationType, int volumeIndex); // allocate memory space and set up pointers. // solutionType 1: double on grid points // 2: integer on grid points // 3: double on elements // 4: integer on elements // interpolationType 1: linear // 2: log... // volumeIndex -1 : add to all volumes in geometry // valid volumeIndex: solution added on specific volume only // return: -1: fail in adding process // solutionIndex to be used in solution access // // there can be two kinds of fields: fields in all volumes and // fields in a specific volume. No field (even in different // volume) should share the same name. int utGridRemoveSolution(utGrid *, char *solutionName); int otGridRemoveSolution(otGrid *, char *solutionName); // this function will also free all the memory allocated for this field int utSolutionIndex(utGrid *, char *solutionName); // solution index is unique in the current implementation int otSolutionIndex(otGrid *, char *solutionName); // solution index is not unique for different solutions. // example: four fields (potential, stressOx, concSi and error) // created for two volumes (Oxide and Si). Potential is defined // in both volumes, but stressOx only on oxide and concSi only on // Si. Error is defined in both volumes on elements, not GridPoint. // Index can be 0 or 1 based, determining by the applications. // VolumeIndex(Geometry *, oxide) = 0 // VolumeIndex(Geometry *, Si) = 1 // SolutionIndex(Grid *, potential) = 0 // SolutionIndex(Grid *, stressOx) = 1 // SolutionIndex(Grid *, concSi) = 1 // SolutionIndex(Grid *, error) = 0 int utSolutionInVolume(utGrid *, char *solutionName); int otSolutionInVolume(otGrid *, char *solutionName); // return volumeIndex the solution is defined on. // -1 if defined on all volumes // following the previous example: // SolutionInVolume(Grid *, potential) = -1 // SolutionInVolume(Grid *, stressOx) = 0 // SolutionInVolume(Grid *, concSi) = 1 // SolutionInVolume(Grid *, error) = -1 int utSolutionType(utGrid *putg, char *solutionName); // return solutionType of the solution // solutionType should be one of {DBL_ON_GP, INT_ON_GP, // DBL_ON_ELEM, INT_ON_ELEM} // Return -2 if solution is not found int utSolutionInterpolationType(utGrid *putg, char *solutionName); // return interpolationType of the solution // interpolationType should be one of // {LIN_INTERPOLATION, LOG_INTERPOLATION} // return -2 if solution is not found // Iterators utForEachGridPoint(utGrid *, utGridPoint *) utForEachGridPointInVolume(utGrid *, int volumeIndex, utGridPoint *) utForEachElement(utGrid *, utElement *) utForEachElementInVolume(utGrid *, int volumeIndex, utElement *) utForEachPointSolution(utGrid *, char *) // give the point solution names stored on the entire grid utForEachPointSolutionInVolume(utGrid *, int volumeIndex, char *) utForEachElementSolution(utGrid *, char *) utForEachElementSolutionInVolume(utGrid *, int volumeIndex, char *) otForEachGridPoint(otGrid *, otGridPoint *) otForEachElement(otGrid *, otElement *) otForEachPointSolution(otGrid *, char *) otForEachElementSolution(otGrid *, char *) // PI for Grid Points // suggest to inline these functions for efficiency double utGridPointCoord(utGridPoint *, int axis); int utGridPointSetDoubleSol(utGridPoint *, int volumeIndex, int solutionIndex, double solValue); // return SUCCESS or FAIL // volumeIndex is only useful for fields on all volumes. int utGridPointSetIntegerSol(utGridPoint *, int volumeIndex, int solutionIndex, int solValue); double utGridPointGetDoubleSol(utGridPoint *, int volumeIndex, int solutionIndex); int utGridPointGetIntegerSol(utGridPoint *, int volumeIndex, int solutionIndex); // Iterator utForEachVolumeAtGridPoint(utGridPoint *, volume *) uutorEachElementWithGridPoint(utGridPoint *, utElement *) double otGridPointCoord(otGridPoint *, int axis); int otGridPointSetDoubleSol(otGridPoint *, intvolumeIndex, int solutionIndex, double solValue); int otGridPointSetIntegerSol(otGridPoint *, int volumeIndex, int solutionIndex, int solValue); double otGridPointGetDoubleSol(otGridPoint *, int volumeIndex, int solutionIndex); int otGridPointGetIntegerSol(otGridPoint *, int volumeIndex, int solutionIndex); void utGridPointSetNumber(utGridPoint *, int GridPointNumber); // Assign a number to the gridpoint so that the number can be // retrieved later by utGridPointNumber int utGridPointNumber(utGridPoint *); // Return the number assigned to the gridpoint earlier by // utGridPointSetNumber // Iterator otForEachVolumeAtGridPoint(otGridPoint *, volume *) otForEachElementWithGridPoint(utGridPoint *, otElement *) // PI on elements utGridPoint *utElementGridPoint(utElement *, int gridPointNumber); Volume *utElementVolume(utElement *); // not presently implemented int *utElementVolume(utElement *) // return volumeIndex for the volume to which the Element belong utElement *ElementNeighbor(utElement *, int neighborNumber); int utElementType(utElement *); // regular or boundary elements? char *utElementFaceBoundaryCondition(utElement *, int faceNumber); // shall we have the mechanism of finding every element face // that is connected to the surfaces for boundary conditions??? // not presently implemented int utElementSetDoubleSol(utElement *, int solutionIndex, double value); int utElementSetIntegerSol(utElement *, int solutionIndex, int value); // returen SUCCESS or FAIL double utElementGetDoubleSol(utElement *, int solutionIndex); int utElementGetIntegerSol(utElement *, int solutionIndex); void utElementSetNumber(utElement *, int ElementNumber); // Assign a number to the gridpoint so that the number can be // retrieved later by utElementNumber int utElementNumber(utElement *); //Return the number assigned to the gridpoint earlier by // utElementSetNumber // Iterators also provided utForEachGridPointInElement(utElement *, utGrid *) utForEachElementNeighbor(utElement *, utElement *) otGridPoint *otElementGridPoint(otElement *, int gridPointNumber); Volume *otElementVolume(otElement *); otElement *ElementNeighbor(otElement *, int neighborNumber); // optional, since tree structure is there. int otElementType(otElement *); // regular or boundary elements? char *otElementFaceBoundaryCondition(otElement *, int faceNumber); // shall we have the mechanism of finding every element face // that is connected to the surfaces for boundary conditions??? int otElementSetDoubleSol(otElement *, int solutionIndex, double value); int otElementSetIntegerSol(otElement *, int solutionIndex, int value); // returen SUCCESS or FAIL double otElementGetDoubleSol(otElement *, int solutionIndex); int otElementGetIntegerSol(otElement *, int solutionIndex); // return 0.0 or 0 if FAIL // Iterators also provided otForEachGridPointInElement(otElement *, otGrid *) otForEachElementNeighbor(otElement *, otElement *) // optional