[cig-commits] r19040 - in long/3D/SNAC/trunk/Snac/plugins: . remesher_BI
echoi at geodynamics.org
echoi at geodynamics.org
Fri Oct 7 09:18:20 PDT 2011
Author: echoi
Date: 2011-10-07 09:18:20 -0700 (Fri, 07 Oct 2011)
New Revision: 19040
Added:
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Make.mm
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Makefile.def
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshCoords.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshElements.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshNodes.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesher.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.c
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.h
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/makefile
long/3D/SNAC/trunk/Snac/plugins/remesher_BI/types.h
Log:
A new scheme of remeshing implemented.
1. Grids of barycenters of new and old hex meshes are created. Tet elements become topological nodes of these grids.
2. Barycentric coordinates of a node of the new barycenter grid are computed within
a containing tet in the old barycenter grid.
3. Tet elements of a regridded mesh takes surrounding elements' values weighted by the barycentric coordinates.
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,154 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Build.c 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Register.h"
+#include "Build.h"
+
+
+void _SnacRemesher_Build( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+ /* Alloc space for the remeshed node coords. */
+ meshExt->newNodeCoords = Memory_Alloc_Array( Coord, mesh->nodeLocalCount, "SnacRemesher" );
+
+ /* Set all else to empty values. */
+ meshExt->newNodes = NULL;
+ meshExt->newElements = NULL;
+ meshExt->nExternalNodes = 0;
+ meshExt->externalNodes = NULL;
+ meshExt->nExternalElements = 0;
+ meshExt->externalElements = NULL;
+ meshExt->nTopInternNodes = 0;
+ meshExt->topInternToLocal = NULL;
+ meshExt->nBotInternNodes = 0;
+ meshExt->botInternToLocal = NULL;
+ meshExt->nTopTriNodes = 0;
+ meshExt->topTriToDomain = NULL;
+ meshExt->nBotTriNodes = 0;
+ meshExt->botTriToDomain = NULL;
+ meshExt->nYLines = 0;
+ meshExt->yLineLTerm = NULL;
+ meshExt->yLineUTerm = NULL;
+ meshExt->yLineNYInds = NULL;
+ meshExt->yLineYInds = NULL;
+ meshExt->yLineLocalInds = NULL;
+}
+
+
+
+#if 0
+
+void _SnacRemesher_Build( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+ /* Keep local copies of the node count info */
+ meshExt->nodeLocalCount = mesh->nodeLocalCount;
+ meshExt->nodeDomainCount = mesh->nodeDomainCount;
+ meshExt->nodeGlobalCount = mesh->nodeGlobalCount;
+ meshExt->elementLocalCount = mesh->elementLocalCount;
+ meshExt->elementDomainCount = mesh->elementDomainCount;
+ meshExt->elementGlobalCount = mesh->elementGlobalCount;
+ Journal_Printf(
+ context->snacDebug,
+ "Remesher is being told: nodeLocalCount: %u, nodeDomainCount: %u, nodeGlobalCount: %u\n",
+ meshExt->nodeLocalCount,
+ meshExt->nodeDomainCount,
+ meshExt->nodeGlobalCount );
+ Journal_Printf(
+ context->snacDebug,
+ "Remesher is being told: elementLocalCount: %u, elementDomainCount %u, elementGlobalCount: %u\n",
+ meshExt->elementLocalCount,
+ meshExt->elementDomainCount,
+ meshExt->elementGlobalCount );
+
+ /* Alloc mem for initial coordinates array. We need only local coordinates here */
+ meshExt->initialNodeCoord = (Coord*)malloc( sizeof(Coord) * meshExt->nodeLocalCount );
+
+ /* Alloc mem for scratch space for calculating new interpolated nodes and elements. Include shadow nodes too.
+ TODO: node and element mem allocation SHOULD be a function provided by the Mesh class */
+ meshExt->newNodeCoord = (Coord*)malloc( sizeof(Coord) * meshExt->nodeDomainCount );
+ meshExt->newNode = (Snac_Node*)ExtensionManager_Malloc( context->mesh->nodeExtensionMgr, meshExt->nodeDomainCount );
+ meshExt->newElement = (Snac_Element*)ExtensionManager_Malloc( context->mesh->elementExtensionMgr, meshExt->elementDomainCount );
+
+ /* Alloc mem for knowing who our neighbour ranks are */
+ meshExt->neighbourRankCount = _HexaMD_Shadow_ProcCount( (HexaMD*)mesh->layout->decomp );
+ meshExt->neighbourRank = (Partition_Index*)malloc( sizeof(Partition_Index) * meshExt->neighbourRankCount );
+
+ /* Top surface shadowing */
+ meshExt->shadowNodeLocalCount = 0;
+ meshExt->shadowNodeLocalArray = 0;
+ meshExt->shadowNodeRemoteCount = 0;
+ meshExt->shadowNodeRemoteArray = 0;
+ meshExt->shadowNodeRemoteCoord = 0;
+ meshExt->shadowNodeRemote = 0;
+ meshExt->shadowElementLocalCount = 0;
+ meshExt->shadowElementLocalArray = 0;
+ meshExt->shadowElementRemoteCount = 0;
+ meshExt->shadowElementRemoteArray = 0;
+ meshExt->shadowElementRemote = 0;
+
+ meshExt->topInternalSet = IndexSet_New( meshExt->nodeLocalCount );
+ meshExt->bottomInternalSet = IndexSet_New( meshExt->nodeLocalCount );
+ meshExt->wallSet = IndexSet_New( meshExt->nodeLocalCount );
+ meshExt->internalSet = IndexSet_New( meshExt->nodeLocalCount );
+ meshExt->topInternalCount = 0;
+ meshExt->bottomInternalCount = 0;
+ meshExt->wallCount = 0;
+ meshExt->internalCount = 0;
+ meshExt->topInternalArray = 0;
+ meshExt->bottomInternalArray = 0;
+ meshExt->wallArray = 0;
+ meshExt->internalArray = 0;
+}
+
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Build.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,47 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Build.h 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Build_h__
+#define __SnacRemesher_Build_h__
+
+
+ void _SnacRemesher_Build( void* _context, void* data );
+
+
+#endif /* __SnacRemesher_Build_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,228 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: ConstructExtensions.c 3066 2005-07-06 22:17:29Z EunseoChoi $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Register.h"
+#include "TestCondFunc.h"
+#include "ConstructExtensions.h"
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+static char CONDITION_STR[] = "remeshCondition";
+static char TIMESTEPCRITERION_STR[] = "remeshTimeStepCriterion";
+static char LENGTHCRITERION_STR[] = "remeshLengthCriterion";
+static char OFF_STR[] = "off";
+static char ON_STR[] = "on";
+static char ONTIMESTEP_STR[] = "onTimeStep";
+static char ONMINLENGTHSCALE_STR[] = "onMinLengthScale";
+static char ONBOTHTIMESTEPLENGTH_STR[] = "onBothTimeStepLength";
+static char MESH_STR[] = "mesh";
+static char MESHTYPE_STR[] = "meshType";
+static char SPHERICAL_STR[] = "spherical";
+static char CARTESIAN_STR[] = "cartesian";
+#ifndef PATH_MAX
+ #define PATH_MAX 1024
+#endif
+
+void _SnacRemesher_ConstructExtensions( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ char* conditionStr;
+ Dictionary_Entry_Value* conditionCriterion;
+ Dictionary* meshDict;
+ Stream* error = Journal_Register( Error_Type, "Remesher" );
+ char tmpBuf[PATH_MAX];
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+ contextExt->debugIC = Journal_Register( Debug_Type, "Remesher-ICs" );
+ contextExt->debugCoords = Journal_Register( Debug_Type, "Remesher-Coords" );
+ contextExt->debugNodes = Journal_Register( Debug_Type, "Remesher-Nodes" );
+ contextExt->debugElements = Journal_Register( Debug_Type, "Remesher-Elements" );
+ contextExt->debugSync = Journal_Register( Debug_Type, "Remesher-Sync" );
+
+ /* Additional tables required over the nodeElementTbl already required by core Snac */
+ Mesh_ActivateNodeNeighbourTbl( mesh );
+ Mesh_ActivateElementNeighbourTbl( mesh );
+
+ /* Work out condition to remesh on */
+ if( !Dictionary_Get( context->dictionary, CONDITION_STR ) ) {
+ Journal_Printf(
+ error,
+ "Warning: No \"%s\" entry in dictionary... will default to \"%s\"\n",
+ CONDITION_STR,
+ OFF_STR );
+ }
+
+ conditionStr = Dictionary_Entry_Value_AsString(
+ Dictionary_GetDefault( context->dictionary, CONDITION_STR, Dictionary_Entry_Value_FromString( OFF_STR ) ) );
+
+ contextExt->OnTimeStep = 0;
+ contextExt->onMinLengthScale = 0;
+ if( !strcmp( conditionStr, OFF_STR ) ) {
+ contextExt->condition = SnacRemesher_Off;
+ Journal_Printf( context->snacInfo, "Remesher is off\n" );
+ }
+ else if( !strcmp( conditionStr, ONTIMESTEP_STR ) ) {
+ contextExt->condition = SnacRemesher_OnTimeStep;
+ conditionCriterion = Dictionary_Get( context->dictionary, TIMESTEPCRITERION_STR );
+ Journal_Printf( context->snacInfo, "Remesher is on... activated based on timeStep\n" );
+
+ if( conditionCriterion ) {
+ contextExt->OnTimeStep = Dictionary_Entry_Value_AsUnsignedInt( conditionCriterion );
+ }
+ else {
+ }
+ Journal_Printf( context->snacInfo, "Remeshing every %u timeSteps\n", contextExt->OnTimeStep );
+ }
+ else if( !strcmp( conditionStr, ONMINLENGTHSCALE_STR ) ) {
+ contextExt->condition = SnacRemesher_OnMinLengthScale;
+ conditionCriterion = Dictionary_Get( context->dictionary, LENGTHCRITERION_STR );
+ Journal_Printf( context->snacInfo, "Remesher is on... activated by minLengthScale\n" );
+
+ if( conditionCriterion ) {
+ contextExt->onMinLengthScale = Dictionary_Entry_Value_AsDouble( conditionCriterion );
+ }
+ else {
+ }
+ Journal_Printf( context->snacInfo, "Remesh when minLengthScale < %g\n", contextExt->onMinLengthScale );
+ }
+ else if( !strcmp( conditionStr, ONBOTHTIMESTEPLENGTH_STR ) ) {
+ contextExt->condition = SnacRemesher_OnBothTimeStepLength;
+ conditionCriterion = Dictionary_Get( context->dictionary, TIMESTEPCRITERION_STR );
+ Journal_Printf( context->snacInfo, "Remesher is on... activated by both timeStep and minLengthScale\n" );
+
+ if( conditionCriterion ) {
+ contextExt->OnTimeStep = Dictionary_Entry_Value_AsUnsignedInt( conditionCriterion );
+ conditionCriterion = Dictionary_Get( context->dictionary, LENGTHCRITERION_STR );
+ contextExt->onMinLengthScale = Dictionary_Entry_Value_AsDouble( conditionCriterion );
+ }
+ else {
+ }
+ Journal_Printf( context->snacInfo, "Remesh every %u timeSteps or wheen minLengthScale < %g\n", contextExt->OnTimeStep, contextExt->onMinLengthScale );
+ }
+ else {
+ contextExt->condition = SnacRemesher_Off;
+ Journal_Printf( context->snacInfo, "Remesher is defaulting to off\n" );
+ Journal_Printf( error, "Provided remesh condition \"%s\" unrecognised\n", conditionStr );
+ }
+
+
+ /* Work out the mesh type */
+ meshDict = Dictionary_Entry_Value_AsDictionary( Dictionary_Get( context->dictionary, MESH_STR ) );
+ if( meshDict ) {
+ char* meshTypeStr;
+
+ if( !Dictionary_Get( meshDict, MESHTYPE_STR ) ) {
+ Journal_Printf(
+ error,
+ "Warning: No \"%s\" entry in \"%s\"... will default to \"%s\"\n",
+ MESHTYPE_STR,
+ MESH_STR,
+ CARTESIAN_STR );
+ }
+
+ meshTypeStr = Dictionary_Entry_Value_AsString(
+ Dictionary_GetDefault( meshDict, MESHTYPE_STR, Dictionary_Entry_Value_FromString( CARTESIAN_STR ) ) );
+
+ if( !strcmp( meshTypeStr, SPHERICAL_STR ) ) {
+ meshExt->meshType = SnacRemesher_Spherical;
+ Journal_Printf( context->snacInfo, "Remesher knows mesh as a spherical mesh\n" );
+ }
+ else if( !strcmp( meshTypeStr, CARTESIAN_STR ) ) {
+ meshExt->meshType = SnacRemesher_Cartesian;
+ Journal_Printf( context->snacInfo, "Remesher knows mesh as a cartesian mesh\n" );
+ }
+ else {
+ meshExt->meshType = SnacRemesher_Cartesian;
+ Journal_Printf( context->snacInfo, "Remesher assuming mesh as a cartesian mesh\n" );
+ Journal_Printf( error, "Provided mesh type \"%s\" unrecognised!\n", meshTypeStr );
+ }
+ }
+ else {
+ meshExt->meshType = SnacRemesher_Cartesian;
+ Journal_Printf( context->snacInfo, "Remesher assuming mesh as a cartesian mesh\n" );
+ Journal_Printf( error, "No \"%s\" entry in dictionary!\n", MESH_STR );
+ }
+ /* Decide whether to restore the bottom surface */
+ contextExt->bottomRestore = 0;
+ if( !strcmp( Dictionary_Entry_Value_AsString( Dictionary_GetDefault( context->dictionary, "bottomRestore", Dictionary_Entry_Value_FromString( OFF_STR ) ) ), ON_STR) )
+ contextExt->bottomRestore = 1;
+
+
+ /* Register these functions for use in VCs */
+ ConditionFunction_Register_Add(
+ context->condFunc_Register,
+ ConditionFunction_New( _SnacRemesher_TestCondFunc, "SnacRemesher_TestCondFunc" ) );
+
+ /* Register these functions for use in VCs */
+ ConditionFunction_Register_Add(
+ context->condFunc_Register,
+ ConditionFunction_New( _SnacRemesher_XFunc, "SnacRemesher_XFunc" ) );
+
+ /* Register these functions for use in VCs */
+ ConditionFunction_Register_Add(
+ context->condFunc_Register,
+ ConditionFunction_New( _SnacRemesher_YFunc, "SnacRemesher_YFunc" ) );
+
+ /* Obtain the keys for the our new entry points... having the keys saves doing a string compare at run time */
+ contextExt->interpolateNodeK = EntryPoint_Register_GetHandle(
+ context->entryPoint_Register,
+ SnacRemesher_EP_InterpolateNode );
+ contextExt->interpolateElementK = EntryPoint_Register_GetHandle(
+ context->entryPoint_Register,
+ SnacRemesher_EP_InterpolateElement );
+
+ /* Prepare the dump file */
+ if( context->rank == 0) {
+ sprintf( tmpBuf, "%s/remeshInfo.%u", context->outputPath, context->rank );
+ if( (contextExt->remesherOut = fopen( tmpBuf, "w+" )) == NULL ) {
+ assert( contextExt->remesherOut /* failed to open file for writing */ );
+ }
+ }
+ /* initialize remeshing counter */
+ contextExt->remeshingCount = 0;
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/ConstructExtensions.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,45 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: ConstructExtensions.h 1396 2004-05-14 02:32:55Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_ConstructExtensions_h__
+#define __SnacRemesher_ConstructExtensions_h__
+
+ void _SnacRemesher_ConstructExtensions( void* _context, void* data );
+
+#endif /* __SnacRemesher_ConstructExtensions_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,90 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Context.c 3250 2006-10-23 06:15:18Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+#include "Context.h"
+#include <stdio.h>
+
+void SnacRemesher_Context_Print( void* _context ) {
+ SnacRemesher_Context* self = (SnacRemesher_Context*)_context;
+
+ printf( "SnacRemesher_Context:\n" );
+ printf(
+ "\tcondition: %s\n",
+ self->condition == SnacRemesher_Off ? "off" :
+ self->condition == SnacRemesher_OnTimeStep ? "OnTimeStep" :
+ self->condition == SnacRemesher_OnMinLengthScale ? "onMinLengthScale" : "Invalid value!" );
+
+ printf( "\tOnTimeStep: %u", self->OnTimeStep );
+ printf( "\tonMinLengthScale: %g\n", self->onMinLengthScale );
+
+ printf( "\tinterpolateNodeK: %u\n", self->interpolateNodeK );
+ printf( "\tinterpolateElementK: %u\n", self->interpolateElementK );
+}
+
+void SnacRemesher_InterpolateNodeFunction( void* _context, SnacRemesher_Context* self,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+
+ SnacRemesher_InterpolateNodeMacro( context, self,
+ nodeInd, elementInd, tetInd,
+ tetNodeInds, weights,
+ dstNodes );
+}
+
+void SnacRemesher_InterpolateElementFunction(
+ void* _context,
+ SnacRemesher_Context* self,
+ Element_LocalIndex dstEltInd,
+ Tetrahedra_Index dstTetInd,
+ Snac_Element* dstEltArray,
+ Element_DomainIndex srcEltInd,
+ Tetrahedra_Index srcTetInd )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+
+ SnacRemesher_InterpolateElementMacro(
+ context,
+ self,
+ dstEltInd,
+ dstTetInd,
+ dstEltArray,
+ srcEltInd,
+ srcTetInd );
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Context.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,127 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Context.h 3250 2006-10-23 06:15:18Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Context_h__
+#define __SnacRemesher_Context_h__
+
+
+ typedef enum {
+ SnacRemesher_Off,
+ SnacRemesher_OnTimeStep,
+ SnacRemesher_OnMinLengthScale,
+ SnacRemesher_OnBothTimeStepLength,
+ SnacRemesher_ConditionMax
+ } SnacRemesher_Condition;
+
+
+ /* Context Information */
+ struct _SnacRemesher_Context {
+ SnacRemesher_Condition condition; /* Type of remeshing criterion condition */
+ unsigned bottomRestore; /* Type of remeshing criterion condition */
+ Index OnTimeStep; /* Time step multiple to remesh on */
+ double onMinLengthScale; /* Min length scale to remesh on */
+
+ EntryPoint_Index interpolateNodeK; /* Key to node interpolation entry point (for speed) */
+ EntryPoint_Index interpolateElementK; /* Key to element interpolation entry point (for speed) */
+
+ Stream* debugIC;
+ Stream* debugCoords;
+ Stream* debugNodes;
+ Stream* debugElements;
+ Stream* debugSync;
+
+ /* Dumping */
+ FILE* remesherOut;
+ Index remeshingCount;
+ };
+
+ /* Print the contents of the context extension */
+ void SnacRemesher_Context_Print( void* _context );
+
+ /* Run the interpolate node entry point */
+ #define SnacRemesher_InterpolateNodeMacro( context, self, \
+ nodeInd, elementInd, tetInd, \
+ tetNodeInds, weights, \
+ dstNodes ) \
+ ( KeyCall( context, self->interpolateNodeK, SnacRemesher_InterpolateNode_CallCast* ) ( \
+ KeyHandle( context, self->interpolateNodeK ), \
+ context, \
+ nodeInd, elementInd, tetInd, \
+ tetNodeInds, weights, \
+ dstNodes ) )
+
+ void SnacRemesher_InterpolateNodeFunction( void* context, SnacRemesher_Context* self,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes );
+
+ #ifdef MACRO_AS_FUNC
+ #define SnacRemesher_InterpolateNode SnacRemesher_InterpolateNodeFunction
+ #else
+ #define SnacRemesher_InterpolateNode SnacRemesher_InterpolateNodeMacro
+ #endif
+
+ /* Run the interpolate element entry point */
+ #define SnacRemesher_InterpolateElementMacro( context, self, \
+ dstElementInd, dstTetInd, \
+ elementArray, \
+ srcElementInd, srcTetInd ) \
+ ( KeyCall( context, self->interpolateElementK, SnacRemesher_InterpolateElement_CallCast* ) ( \
+ KeyHandle( context, self->interpolateElementK ), \
+ context, \
+ dstElementInd, \
+ dstTetInd, \
+ elementArray, \
+ srcElementInd, \
+ srcTetInd ) )
+ void SnacRemesher_InterpolateElementFunction( void* _context,
+ SnacRemesher_Context* self,
+ Element_LocalIndex dstEltInd,
+ Tetrahedra_Index dstTetInd,
+ Snac_Element* dstEltArray,
+ Element_DomainIndex srcEltInd,
+ Tetrahedra_Index srcTetInd );
+
+ #ifdef MACRO_AS_FUNC
+ #define SnacRemesher_InterpolateElement SnacRemesher_InterpolateElementFunction
+ #else
+ #define SnacRemesher_InterpolateElement SnacRemesher_InterpolateElementMacro
+ #endif
+
+#endif /* __SnacRemesher_Context_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,83 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: DeleteExtensions.c 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Register.h"
+#include "DeleteExtensions.h"
+
+
+void _SnacRemesher_DeleteExtensions( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+
+ /*
+ ** Probably will not need to do this.
+ */
+
+ if( meshExt->newNodes ) {
+ ExtensionManager_Free( mesh->nodeExtensionMgr, meshExt->newNodes );
+ }
+
+ if( meshExt->newElements ) {
+ ExtensionManager_Free( mesh->nodeExtensionMgr, meshExt->newElements );
+ }
+
+
+ /*
+ ** Kill the mesh extension.
+ */
+
+ KillArray( meshExt->newNodeCoords );
+ KillArray( meshExt->externalNodes );
+ KillArray( meshExt->externalElements );
+ KillArray( meshExt->topInternToLocal );
+ KillArray( meshExt->botInternToLocal );
+ KillArray( meshExt->topTriToDomain );
+ KillArray( meshExt->botTriToDomain );
+ KillArray( meshExt->yLineLTerm );
+ KillArray( meshExt->yLineUTerm );
+ KillArray( meshExt->yLineNYInds );
+ KillArray2D( meshExt->nYLines, meshExt->yLineYInds );
+ KillArray2D( meshExt->nYLines, meshExt->yLineLocalInds );
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/DeleteExtensions.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,45 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: DeleteExtensions.h 1396 2004-05-14 02:32:55Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_DeleteExtensions_h__
+#define __SnacRemesher_DeleteExtensions_h__
+
+ void _SnacRemesher_DeleteExtensions( void* _context, void* data );
+
+#endif /* __SnacRemesher_DeleteExtensions_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,192 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: EntryPoint.c 3250 2006-10-23 06:15:18Z LukeHodkinson $
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+
+/* Textual name of this class */
+const Type SnacRemesher_EntryPoint_Type = "SnacRemesher_EntryPoint";
+
+
+SnacRemesher_EntryPoint* SnacRemesher_EntryPoint_New( const Name name, unsigned int castType ) {
+ return _SnacRemesher_EntryPoint_New(
+ sizeof(SnacRemesher_EntryPoint),
+ SnacRemesher_EntryPoint_Type,
+ _EntryPoint_Delete,
+ _EntryPoint_Print,
+ NULL,
+ _SnacRemesher_EntryPoint_GetRun,
+ name,
+ castType );
+}
+
+void SnacRemesher_EntryPoint_Init( void* snac_EntryPoint, const Name name, unsigned int castType ) {
+ SnacRemesher_EntryPoint* self = (SnacRemesher_EntryPoint*)snac_EntryPoint;
+
+ /* General info */
+ self->type = SnacRemesher_EntryPoint_Type;
+ self->_sizeOfSelf = sizeof(SnacRemesher_EntryPoint);
+ self->_deleteSelf = False;
+
+ /* Virtual info */
+ self->_delete = _EntryPoint_Delete;
+ self->_print = _EntryPoint_Print;
+ self->_copy = NULL;
+ self->_getRun = _SnacRemesher_EntryPoint_GetRun;
+ _Stg_Class_Init( (Stg_Class*)self );
+ _Stg_Object_Init( (Stg_Object*)self, name, NON_GLOBAL );
+ _EntryPoint_Init( (EntryPoint*)self, castType );
+ _ContextEntryPoint_Init( (ContextEntryPoint*)self );
+ _Snac_EntryPoint_Init( (Snac_EntryPoint*)self );
+
+ /* SnacRemesher_EntryPoint info */
+ _SnacRemesher_EntryPoint_Init( self );
+}
+
+SnacRemesher_EntryPoint* _SnacRemesher_EntryPoint_New(
+ SizeT _sizeOfSelf,
+ Type type,
+ Stg_Class_DeleteFunction* _delete,
+ Stg_Class_PrintFunction* _print,
+ Stg_Class_CopyFunction* _copy,
+ EntryPoint_GetRunFunction* _getRun,
+ Name name,
+ unsigned int castType )
+{
+ SnacRemesher_EntryPoint* self;
+
+ /* Allocate memory */
+ assert( _sizeOfSelf >= sizeof(SnacRemesher_EntryPoint) );
+ self = (SnacRemesher_EntryPoint*)_Snac_EntryPoint_New(
+ _sizeOfSelf,
+ type,
+ _delete,
+ _print,
+ _copy,
+ _getRun,
+ name,
+ castType );
+
+ /* General info */
+
+ /* Virtual info */
+
+ /* SnacRemesher_EntryPoint info */
+ _SnacRemesher_EntryPoint_Init( self );
+
+ return self;
+}
+
+void _SnacRemesher_EntryPoint_Init( SnacRemesher_EntryPoint* self ) {
+ /* General and Virtual info should already be set */
+
+ /* SnacRemesher_EntryPoint info */
+}
+
+
+Func_Ptr _SnacRemesher_EntryPoint_GetRun( void* snac_EntryPoint ) {
+ SnacRemesher_EntryPoint* self = (SnacRemesher_EntryPoint*)snac_EntryPoint;
+
+ switch( self->castType ) {
+ case SnacRemesher_InterpolateNode_CastType:
+ return _SnacRemesher_EntryPoint_Run_InterpolateNode;
+
+ case SnacRemesher_InterpolateElement_CastType:
+ return _SnacRemesher_EntryPoint_Run_InterpolateElement;
+ default:
+ return _Snac_EntryPoint_GetRun( self );
+ }
+}
+
+
+void _SnacRemesher_EntryPoint_Run_InterpolateNode( void* entryPoint, void* context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes )
+{
+ SnacRemesher_EntryPoint* self = (SnacRemesher_EntryPoint*)entryPoint;
+ Hook_Index hookIndex;
+
+ #ifdef USE_PROFILE
+ Stg_CallGraph_Push( stgCallGraph, _SnacRemesher_EntryPoint_Run_InterpolateNode, self->name );
+ #endif
+
+ for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
+ void* funcPtr;
+
+ funcPtr = ((Hook*)self->hooks->data[hookIndex])->funcPtr;
+ (*(SnacRemesher_InterpolateNode_Cast*)funcPtr)( context,
+ nodeInd, elementInd, tetInd,
+ tetNodeInds, weights,
+ dstNodes );
+ }
+
+ #ifdef USE_PROFILE
+ Stg_CallGraph_Pop( stgCallGraph );
+ #endif
+}
+
+void _SnacRemesher_EntryPoint_Run_InterpolateElement( void* entryPoint, void* context,
+ unsigned dstElementInd, unsigned dstTetInd,
+ Snac_Element* elementArray,
+ unsigned srcElementInd, unsigned srcTetInd )
+{
+ SnacRemesher_EntryPoint* self = (SnacRemesher_EntryPoint*)entryPoint;
+ Hook_Index hookIndex;
+
+ #ifdef USE_PROFILE
+ Stg_CallGraph_Push( stgCallGraph, _SnacRemesher_EntryPoint_Run_InterpolateElement, self->name );
+ #endif
+
+ for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
+ void* funcPtr;
+
+ funcPtr = ((Hook*)self->hooks->data[hookIndex])->funcPtr;
+ (*(SnacRemesher_InterpolateElement_Cast*)funcPtr)( context,
+ dstElementInd, dstTetInd,
+ elementArray,
+ srcElementInd, srcTetInd );
+ }
+
+ #ifdef USE_PROFILE
+ Stg_CallGraph_Pop( stgCallGraph );
+ #endif
+}
+
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/EntryPoint.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,109 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: EntryPoint.h 3250 2006-10-23 06:15:18Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_EntryPoint_h__
+#define __SnacRemesher_EntryPoint_h__
+
+ /* Templates for default entry point type */
+ typedef void (SnacRemesher_InterpolateNode_Cast)( void* context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes );
+
+ typedef void (SnacRemesher_InterpolateElement_Cast)( void* context,
+ unsigned dstElementInd, unsigned dstTetInd,
+ Snac_Element* elementArray,
+ unsigned srcElementInd, unsigned srcTetInd );
+
+ typedef void (SnacRemesher_InterpolateNode_CallCast)( void* entryPoint, void* context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes );
+
+ typedef void (SnacRemesher_InterpolateElement_CallCast)( void* entryPoint, void* context,
+ unsigned dstElementInd, unsigned dstTetInd,
+ Snac_Element* elementArray,
+ unsigned srcElementInd, unsigned srcTetInd );
+
+ #define SnacRemesher_InterpolateNode_CastType (Snac_CastType_MAX + 1)
+ #define SnacRemesher_InterpolateElement_CastType (SnacRemesher_InterpolateNode_CastType + 1)
+ #define SnacRemesher_CastType_MAX (SnacRemesher_InterpolateElement_CastType + 1)
+
+ /** Textual name of this class */
+ extern const Type SnacRemesher_EntryPoint_Type;
+
+ /** SnacRemesher_EntryPoint info */
+ #define __SnacRemesher_EntryPoint \
+ /* General info */ \
+ __Snac_EntryPoint \
+ \
+ /* Virtual info */ \
+ \
+ /* SnacRemesher_EntryPoint info */
+
+ struct _SnacRemesher_EntryPoint { __SnacRemesher_EntryPoint };
+
+ /* Create a new SnacRemesher_EntryPoint */
+ SnacRemesher_EntryPoint* SnacRemesher_EntryPoint_New( const Name name, unsigned int castType );
+
+ /* Initialise an SnacRemesher_EntryPoint */
+ void SnacRemesher_EntryPoint_Init( void* snac_EntryPoint, const Name name, unsigned int castType );
+
+ /* Creation implementation */
+ SnacRemesher_EntryPoint* _SnacRemesher_EntryPoint_New(
+ SizeT _sizeOfSelf,
+ Type type,
+ Stg_Class_DeleteFunction* _delete,
+ Stg_Class_PrintFunction* _print,
+ Stg_Class_CopyFunction* _copy,
+ EntryPoint_GetRunFunction* _getRun,
+ const Name name,
+ unsigned int castType);
+
+ /* Initialisation implementation */
+ void _SnacRemesher_EntryPoint_Init( SnacRemesher_EntryPoint* self );
+
+ /* Default GetRun implementation */
+ Func_Ptr _SnacRemesher_EntryPoint_GetRun( void* snac_EntryPoint );
+
+ /* Snac remesher entry point run... for interpolating a node */
+ void _SnacRemesher_EntryPoint_Run_InterpolateNode( void* entryPoint, void* context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes );
+
+ /* Snac remesher entry point run... for interpolating an element */
+ void _SnacRemesher_EntryPoint_Run_InterpolateElement( void* entryPoint, void* context,
+ unsigned dstElementInd, unsigned dstTetInd,
+ Snac_Element* elementArray,
+ unsigned srcElementInd, unsigned srcTetInd );
+
+#endif /* __SnacRemesher_EntryPoint_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,1048 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** Comments:
+** Not sure ShadowElementSetLocal is needed as I think it now has the same values as ShadowElementSetCurrent.
+**
+** $Id: InitialConditions.c 3254 2006-10-26 08:25:11Z EunseoChoi $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Register.h"
+#include "InitialConditions.h"
+#include "Utils.h"
+
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#ifndef PATH_MAX
+ #define PATH_MAX 1024
+#endif
+
+void _SnacRemesher_InitialConditions( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ unsigned lNode_i;
+ IndexSet* walls[6];
+ IndexSet* bulk;
+ IndexSet* topIntern;
+ IndexSet* botIntern;
+
+ void _SnacRemesher_TriangulateXZPlane(
+ void* _context,
+ IndexSet* planeNodes,
+ unsigned gYInd,
+ unsigned* nTriNodes,
+ unsigned** triToDomain );
+
+
+ /*
+ ** Firstly, backup all coords into the 'newNodeCoords' coord block.
+ */
+ if( context->restartTimestep > 0 ) {
+ FILE *fp;
+ char path[PATH_MAX];
+ double x,y,z;
+
+ sprintf(path, "%s/snac.initCoord.%d.%06d.restart",context->outputPath,context->rank,context->restartTimestep);
+ Journal_Firewall( ( (fp=fopen(path,"r")) != NULL), context->snacError, "Can't find %s\n", path );
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ fscanf( fp, "%le %le %le", &x,&y,&z);
+ meshExt->newNodeCoords[lNode_i][0] = x;
+ meshExt->newNodeCoords[lNode_i][1] = y;
+ meshExt->newNodeCoords[lNode_i][2] = z;
+ }
+ }
+ else {
+ if( meshExt->meshType == SnacRemesher_Cartesian ) {
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ Vector_Set( meshExt->newNodeCoords[lNode_i], mesh->nodeCoord[lNode_i] );
+ }
+ }
+ else {
+ /* Convert cartesian coordinates to spherical coordinates and store. */
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ double x = mesh->nodeCoord[lNode_i][0];
+ double y = mesh->nodeCoord[lNode_i][1];
+ double z = mesh->nodeCoord[lNode_i][2];
+
+ meshExt->newNodeCoords[lNode_i][0] = SnacArcTan( y, x );
+ meshExt->newNodeCoords[lNode_i][1] = sqrt( x * x + y * y + z * z );
+ meshExt->newNodeCoords[lNode_i][2] = acos( z / meshExt->newNodeCoords[lNode_i][1] );
+ }
+ }
+ }
+
+
+ /*
+ ** Generate index arrays into local coordinate space for top and bottom (internal) walls.
+ */
+
+ walls[0] = RegularMeshUtils_CreateGlobalLeftSet( mesh );
+ walls[1] = RegularMeshUtils_CreateGlobalRightSet( mesh );
+ walls[2] = RegularMeshUtils_CreateGlobalFrontSet( mesh );
+ walls[3] = RegularMeshUtils_CreateGlobalBackSet( mesh );
+ walls[4] = RegularMeshUtils_CreateGlobalTopSet( mesh );
+ walls[5] = RegularMeshUtils_CreateGlobalBottomSet( mesh );
+ bulk = IndexSet_New( mesh->nodeLocalCount );
+
+ topIntern = IndexSet_New( mesh->nodeLocalCount );
+ botIntern = IndexSet_New( mesh->nodeLocalCount );
+
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ if( IndexSet_IsMember( walls[4], lNode_i ) ) {
+ IndexSet_Add( topIntern, lNode_i );
+ }
+ else if( IndexSet_IsMember( walls[5], lNode_i ) )
+ {
+ IndexSet_Add( botIntern, lNode_i );
+ }
+ else {
+ /* Also generate the bulk indices while we're at it. */
+ IndexSet_Add( bulk, lNode_i );
+ }
+ }
+
+ IndexSet_GetMembers( topIntern, &meshExt->nTopInternNodes, &meshExt->topInternToLocal );
+ IndexSet_GetMembers( botIntern, &meshExt->nBotInternNodes, &meshExt->botInternToLocal );
+
+ /* These walls aren't needed any more. */
+ Stg_Class_Delete( walls[0] );
+ Stg_Class_Delete( walls[1] );
+ Stg_Class_Delete( walls[2] );
+ Stg_Class_Delete( walls[3] );
+
+
+ /*
+ ** Create triangulations for the top and bottom walls using domain indices.
+ */
+
+ if( walls[4]->membersCount > 0 ) {
+ _SnacRemesher_TriangulateXZPlane(
+ context,
+ walls[4],
+ decomp->nodeGlobal3DCounts[1] - 1,
+ &meshExt->nTopTriNodes,
+ &meshExt->topTriToDomain );
+ }
+ else {
+ meshExt->nTopTriNodes = 0;
+ meshExt->topTriToDomain = NULL;
+ }
+
+ if( walls[5]->membersCount > 0 ) {
+ _SnacRemesher_TriangulateXZPlane( context, walls[5], 0, &meshExt->nBotTriNodes, &meshExt->botTriToDomain );
+ }
+ else {
+ meshExt->nBotTriNodes = 0;
+ meshExt->botTriToDomain = NULL;
+ }
+
+ /* Walls are no longer required. */
+ Stg_Class_Delete( walls[4] );
+ Stg_Class_Delete( walls[5] );
+
+
+ /*
+ ** Build lists of y-lines for interpolating bulk nodes efficiently.
+ */
+
+ {
+ unsigned nBulkNodes;
+ Node_LocalIndex* bulkNodes;
+ unsigned bulk_i;
+ unsigned nYLines;
+ unsigned* yLineX;
+ unsigned* yLineZ;
+
+ /*
+ ** First, extract the number of y-lines and their x,z offsets.
+ */
+
+ /* Extract the bulk local node indices and destroy the set. */
+ IndexSet_GetMembers( bulk, &nBulkNodes, &bulkNodes );
+ Stg_Class_Delete( bulk );
+
+ /* Setup yLine info. */
+ nYLines = 0;
+ yLineX = Memory_Alloc_Array( unsigned, 1, "SnacRemesher" );
+ yLineZ = Memory_Alloc_Array( unsigned, 1, "SnacRemesher" );
+
+ /* Calculate the number of unique y-lines and their x, z offsets. */
+ for( bulk_i = 0; bulk_i < nBulkNodes; bulk_i++ ) {
+ Node_GlobalIndex gNodeInd;
+ IJK ijk;
+ unsigned yLine_i;
+
+ gNodeInd = Mesh_NodeMapLocalToGlobal( mesh, bulkNodes[bulk_i] );
+ RegularMeshUtils_Node_1DTo3D( decomp, gNodeInd, &ijk[0], &ijk[1], &ijk[2] );
+
+ /* Is this one unique? */
+ for( yLine_i = 0; yLine_i < nYLines; yLine_i++ ) {
+ if( yLineX[yLine_i] == ijk[0] && yLineZ[yLine_i] == ijk[2] ) {
+ break;
+ }
+ }
+
+ /* If not, skip. */
+ if( yLine_i < nYLines ) {
+ continue;
+ }
+
+ /* If so, add it to the list. */
+ yLineX = Memory_Realloc_Array( yLineX, unsigned, nYLines + 1 );
+ yLineZ = Memory_Realloc_Array( yLineZ, unsigned, nYLines + 1 );
+ yLineX[nYLines] = ijk[0];
+ yLineZ[nYLines] = ijk[2];
+ nYLines++;
+ }
+
+ /* If there were none, then fix the arrays. */
+ if( nYLines == 0 ) {
+ Memory_Free( yLineX );
+ yLineX = NULL;
+ Memory_Free( yLineZ );
+ yLineZ = NULL;
+ }
+ else {
+ IndexSet* locals;
+ unsigned yLine_i;
+
+ /* If we're here, then there are local y-lines and we need to fill incident local nodes. Start
+ by setting up the arrays. */
+ meshExt->nYLines = nYLines;
+ meshExt->yLineLTerm = Memory_Alloc_Array( unsigned, nYLines, "SnacRemesher" );
+ meshExt->yLineUTerm = Memory_Alloc_Array( unsigned, nYLines, "SnacRemesher" );
+ meshExt->yLineNYInds = Memory_Alloc_Array( unsigned, nYLines, "SnacRemesher" );
+ meshExt->yLineYInds = Memory_Alloc_Array( unsigned*, nYLines, "SnacRemesher" );
+ meshExt->yLineLocalInds = Memory_Alloc_Array( unsigned*, nYLines, "SnacRemesher" );
+
+ locals = IndexSet_New( mesh->nodeLocalCount );
+
+ /* Loop over y-lines */
+ for( yLine_i = 0; yLine_i < nYLines; yLine_i++ ) {
+ IndexSet_RemoveAll( locals );
+
+ /* Loop over local bulk nodes. */
+ for( bulk_i = 0; bulk_i < nBulkNodes; bulk_i++ ) {
+ Node_GlobalIndex gNodeInd;
+ IJK ijk;
+
+ gNodeInd = Mesh_NodeMapLocalToGlobal( mesh, bulkNodes[bulk_i] );
+ RegularMeshUtils_Node_1DTo3D( decomp, gNodeInd, &ijk[0], &ijk[1], &ijk[2] );
+
+ if( ijk[0] == yLineX[yLine_i] && ijk[2] == yLineZ[yLine_i] ) {
+ IndexSet_Add( locals, bulkNodes[bulk_i] );
+ }
+ }
+
+ /* Add them to the master arrays. */
+ {
+ unsigned yLine_j;
+ IJK ijk;
+
+ IndexSet_GetMembers( locals, &meshExt->yLineNYInds[yLine_i], &meshExt->yLineLocalInds[yLine_i] );
+ meshExt->yLineYInds[yLine_i] = Memory_Alloc_Array( unsigned,
+ meshExt->yLineNYInds[yLine_i],
+ "SnacRemesher" );
+
+ /* Extract the global y-index for each local index. */
+ for( yLine_j = 0; yLine_j < meshExt->yLineNYInds[yLine_i]; yLine_j++ ) {
+ Node_GlobalIndex gNodeInd;
+
+ gNodeInd = Mesh_NodeMapLocalToGlobal( mesh, meshExt->yLineLocalInds[yLine_i][yLine_j] );
+ RegularMeshUtils_Node_1DTo3D( decomp, gNodeInd, &ijk[0], &ijk[1], &ijk[2] );
+
+ meshExt->yLineYInds[yLine_i][yLine_j] = ijk[1];
+ }
+
+ /* Set up the terminals. */
+ meshExt->yLineLTerm[yLine_i] = RegularMeshUtils_Node_Global3DToGlobal1D( decomp,
+ ijk[0],
+ 0,
+ ijk[2] );
+ meshExt->yLineUTerm[yLine_i] = RegularMeshUtils_Node_Global3DToGlobal1D( decomp,
+ ijk[0],
+ decomp->nodeGlobal3DCounts[1] - 1,
+ ijk[2] );
+ }
+ }
+
+ Stg_Class_Delete( locals );
+ }
+
+ if( yLineX ) {
+ Memory_Free( yLineX );
+ }
+
+ if( yLineZ ) {
+ Memory_Free( yLineZ );
+ }
+ }
+
+
+ /*
+ ** Currently, the terminals are stored in global index format. We need to determine if the terminals are
+ ** actually locally stored or remotely. If locally, then convert the global index to a local one. If remotely,
+ ** then add it to the 'sync' class and modify the global index to look in the right sync'ed place.
+ */
+
+ {
+ unsigned yLine_i;
+ SnacSync* sync;
+ unsigned nLocals = 0;
+ unsigned* locals;
+ unsigned nRequired = 0;
+ unsigned* required;
+ unsigned z_i;
+ unsigned* srcMap;
+
+ /* Create a new sync class. */
+ sync = SnacSync_New( "SnacRemesher_SnacSync" );
+
+ /* Initialise the required array. */
+ required = Memory_Alloc_Array( unsigned, 1, "SnacSync" );
+
+ for( yLine_i = 0; yLine_i < meshExt->nYLines; yLine_i++ ) {
+ unsigned term;
+
+ /* Check the lower terminal. */
+ term = Mesh_NodeMapGlobalToLocal( mesh, meshExt->yLineLTerm[yLine_i] );
+ if( term < mesh->nodeLocalCount ) {
+ /* Store local index. */
+ meshExt->yLineLTerm[yLine_i] = term;
+ }
+ else {
+ /* Add this terminal to the sync-remote array and modify its index to be:
+ nodeLocalCount + remote-index */
+ required = Memory_Realloc_Array( required, unsigned, nRequired + 1 );
+ required[nRequired] = meshExt->yLineLTerm[yLine_i];
+ meshExt->yLineLTerm[yLine_i] = mesh->nodeLocalCount + nRequired;
+ nRequired++;
+ }
+
+ /* Check the upper terminal. */
+ term = Mesh_NodeMapGlobalToLocal( mesh, meshExt->yLineUTerm[yLine_i] );
+ if( term < mesh->nodeLocalCount ) {
+ /* Store local index. */
+ meshExt->yLineUTerm[yLine_i] = term;
+ }
+ else {
+ /* Add this terminal to the sync-remote array and modify its index to be:
+ nodeLocalCount + remote-index */
+ required = Memory_Realloc_Array( required, unsigned, nRequired + 1 );
+ required[nRequired] = meshExt->yLineUTerm[yLine_i];
+ meshExt->yLineUTerm[yLine_i] = mesh->nodeLocalCount + nRequired;
+ nRequired++;
+ }
+ }
+
+ /* Fix up the required array. */
+ if( nRequired == 0 ) {
+ KillArray( required );
+ }
+
+ /* Begin the local array. */
+ locals = Memory_Alloc_Array( unsigned, 1, "SnacSync" );
+
+ /* Add local terminals. */
+ for( z_i = 0; z_i < decomp->nodeGlobal3DCounts[2]; z_i++ ) {
+ unsigned x_i;
+
+ for( x_i = 0; x_i < decomp->nodeGlobal3DCounts[0]; x_i++ ) {
+ Node_GlobalIndex gLower;
+ Node_GlobalIndex gUpper;
+ Node_LocalIndex lLower;
+ Node_LocalIndex lUpper;
+
+ gLower = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, x_i, 0, z_i );
+ gUpper = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, x_i, decomp->nodeGlobal3DCounts[1] - 1, z_i );
+ lLower = Mesh_NodeMapGlobalToLocal( mesh, gLower );
+ lUpper = Mesh_NodeMapGlobalToLocal( mesh, gUpper );
+
+ if( lLower < mesh->nodeLocalCount ) {
+ locals = Memory_Realloc_Array( locals, unsigned, nLocals + 1 );
+ locals[nLocals] = gLower;
+ nLocals++;
+ }
+
+ if( lUpper < mesh->nodeLocalCount ) {
+ locals = Memory_Realloc_Array( locals, unsigned, nLocals + 1 );
+ locals[nLocals] = gUpper;
+ nLocals++;
+ }
+ }
+ }
+
+ /* If no locals, fix array. */
+ if( nLocals == 0 ) {
+ KillArray( locals );
+ }
+
+ /* Negotiate minimum comms. */
+ SnacSync_Negotiate( sync, mesh->nodeGlobalCount, nLocals, locals, nRequired, required, decomp->communicator );
+
+ /* Store the sync class. */
+ meshExt->sync = sync;
+
+
+ /*
+ ** Build a map to move source values from the received order (which is essentially anything) to the order
+ ** specified in 'required'.
+ */
+
+ if( sync->netSource ) {
+ unsigned proc_i;
+ unsigned srcInd = 0;
+
+ /* Alloc memory. */
+ srcMap = Memory_Alloc_Array( unsigned, sync->netSource, "SnacSync" );
+
+ /* Map 'em. */
+ for( proc_i = 0; proc_i < sync->nProcs; proc_i++ ) {
+ unsigned src_i;
+
+ for( src_i = 0; src_i < sync->nSource[proc_i]; src_i++ ) {
+ unsigned req_i;
+
+ for( req_i = 0; req_i < nRequired; req_i++ ) {
+ if( sync->source[proc_i][src_i] == required[req_i] ) {
+ srcMap[srcInd] = req_i;
+ break;
+ }
+ }
+
+ srcInd++;
+ }
+ }
+ }
+ else {
+ srcMap = NULL;
+ }
+
+
+ /*
+ ** Build a mapping from sink indices to local indices and initialise the send/recv component of the sync class.
+ */
+
+ {
+ unsigned* snkMap;
+
+ if( sync->netSink ) {
+ unsigned proc_i;
+ unsigned snkInd = 0;
+
+ snkMap = Memory_Alloc_Array( unsigned, sync->netSink, "SnacRemesher" );
+
+ for( proc_i = 0; proc_i < sync->nProcs; proc_i++ ) {
+ unsigned snk_i;
+
+ for( snk_i = 0; snk_i < sync->nSink[proc_i]; snk_i++ ) {
+ snkMap[snkInd] = Mesh_NodeMapGlobalToLocal( mesh, sync->sink[proc_i][snk_i] );
+ snkInd++;
+ }
+ }
+ }
+ else {
+ snkMap = NULL;
+ }
+
+ /* Initialise. */
+ SnacSync_SendRecvInitialise( sync, sizeof(double), snkMap, sizeof(Coord), srcMap, sizeof(double) );
+
+ /* Free resources. */
+ FreeArray( snkMap );
+ FreeArray( srcMap );
+ }
+
+ /* Free other arrays. */
+ FreeArray( locals );
+ FreeArray( required );
+ }
+}
+
+
+void _SnacRemesher_TriangulateXZPlane(
+ void* _context,
+ IndexSet* planeNodes,
+ unsigned gYInd,
+ unsigned* nTriNodes,
+ unsigned** triToDomain )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ IJK gSize;
+ IJK dSize;
+ IJK pos;
+
+
+ /*
+ ** Definitley not the fastest way of doing this, but it should work none-the-less.
+ */
+
+ gSize[0] = decomp->nodeGlobal3DCounts[0];
+ gSize[1] = decomp->nodeGlobal3DCounts[1];
+ gSize[2] = decomp->nodeGlobal3DCounts[2];
+ pos[1] = gYInd;
+
+ /* Calculate the domain x size. */
+ for( pos[2] = 0; pos[2] < gSize[2]; pos[2]++ ) {
+ unsigned xMin, xMax;
+ Bool found = False;
+
+ xMax = 0;
+
+ for( pos[0] = 0; pos[0] < gSize[0]; pos[0]++ ) {
+ Node_GlobalIndex gNodeInd;
+ Node_DomainIndex dNodeInd;
+
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0], pos[1], pos[2] );
+ dNodeInd = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+
+ if( !found && dNodeInd < mesh->nodeDomainCount ) {
+ xMin = pos[0];
+ found = True;
+ }
+ else if( found && dNodeInd >= mesh->nodeDomainCount ) {
+ xMax = pos[0];
+ break;
+ }
+ }
+
+ if( found ) {
+ if( xMax == 0 ) {
+ dSize[0] = gSize[0] - xMin;
+ }
+ else {
+ dSize[0] = xMax - xMin;
+ }
+ break;
+ }
+ }
+
+ /* Calculate the domain z size. */
+ for( pos[0] = 0; pos[0] < gSize[0]; pos[0]++ ) {
+ unsigned zMin, zMax;
+ Bool found = False;
+
+ zMax = 0;
+
+ for( pos[2] = 0; pos[2] < gSize[2]; pos[2]++ ) {
+ Node_GlobalIndex gNodeInd;
+ Node_DomainIndex dNodeInd;
+
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0], pos[1], pos[2] );
+ dNodeInd = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+
+ if( !found && dNodeInd < mesh->nodeDomainCount ) {
+ zMin = pos[2];
+ found = True;
+ }
+ else if( found && dNodeInd >= mesh->nodeDomainCount ) {
+ zMax = pos[2];
+ break;
+ }
+ }
+
+ if( found ) {
+ if( zMax == 0 ) {
+ dSize[2] = gSize[2] - zMin;
+ }
+ else {
+ dSize[2] = zMax - zMin;
+ }
+ break;
+ }
+ }
+
+
+ /*
+ ** Set up the destination values/arrays.
+ */
+
+ *nTriNodes = (dSize[0] - 1) * (dSize[2] - 1) * 6;
+ *triToDomain = Memory_Alloc_Array( Node_DomainIndex, *nTriNodes, "SnacRemesher" );
+
+
+ /*
+ ** Do the triangulation.
+ */
+
+ {
+ unsigned curTri = 0;
+
+ for( pos[2] = 0; pos[2] < gSize[2] - 1; pos[2]++ ) {
+ for( pos[0] = 0; pos[0] < gSize[0] - 1; pos[0]++ ) {
+ Node_GlobalIndex gNodeInd;
+ Node_DomainIndex dNodeInd[4];
+
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0], pos[1], pos[2] );
+ dNodeInd[0] = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0] + 1, pos[1], pos[2] );
+ dNodeInd[1] = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0] + 1, pos[1], pos[2] + 1 );
+ dNodeInd[2] = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+ gNodeInd = RegularMeshUtils_Node_Global3DToGlobal1D( decomp, pos[0], pos[1], pos[2] + 1 );
+ dNodeInd[3] = Mesh_NodeMapGlobalToDomain( mesh, gNodeInd );
+
+ if( dNodeInd[0] < mesh->nodeDomainCount && dNodeInd[1] < mesh->nodeDomainCount &&
+ dNodeInd[2] < mesh->nodeDomainCount && dNodeInd[3] < mesh->nodeDomainCount )
+ {
+ /* If we are here then we've found a valid planar element and can proceed to triangulate it. */
+ (*triToDomain)[(curTri * 3) + 0] = dNodeInd[0];
+ (*triToDomain)[(curTri * 3) + 1] = dNodeInd[1];
+ (*triToDomain)[(curTri * 3) + 2] = dNodeInd[3];
+ curTri++;
+
+ (*triToDomain)[(curTri * 3) + 0] = dNodeInd[1];
+ (*triToDomain)[(curTri * 3) + 1] = dNodeInd[2];
+ (*triToDomain)[(curTri * 3) + 2] = dNodeInd[3];
+ curTri++;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+#if 0
+/*
+** Removed for a rewrite. Luke - 02/07/2005
+*/
+
+
+/*
+static void _SnacRemesher_CheckForShadowNode(
+ Snac_Context* context,
+ SnacRemesher_Context* contextExt,
+ Node_GlobalIndex node_gI,
+ Node_LocalIndex node_lI,
+ IndexSet** ShadowNodeSetCurrent,
+ IndexSet** ShadowNodeSetLocal,
+ IndexSet** ShadowNodeSetRemote );
+
+static void _SnacRemesher_CheckForShadowElement(
+ Snac_Context* context,
+ SnacRemesher_Context* contextExt,
+ Element_GlobalIndex element_gI,
+ Element_LocalIndex element_lI,
+ IndexSet** ShadowElementSetCurrent,
+ IndexSet** ShadowElementSetLocal,
+ IndexSet** ShadowElementSetRemote );
+*/
+
+
+void _SnacRemesher_InitialConditions( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ MeshLayout* layout = mesh->layout;
+ Topology* eTopology = layout->elementLayout->topology;
+ HexaMD* decomp = (HexaMD*)layout->decomp;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ IndexSet** gWallSet;
+ Partition_Index rn_I;
+ Partition_Index rnCount = meshExt->neighbourRankCount;
+ IndexSet** shadowNodeSetLocal;
+ IndexSet** shadowNodeSetRemote;
+ IndexSet** shadowElementSetLocal;
+ IndexSet** shadowElementSetRemote;
+ Node_GlobalIndex node_gI;
+ Element_GlobalIndex element_gI;
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+ /* If cartesion mesh, merely make a copy of initial node coordinates */
+ if( meshExt->meshType == SnacRemesher_Cartesian || meshExt->meshType == SnacRemesher_Spherical ) {
+ memcpy( meshExt->initialNodeCoord, mesh->nodeCoord, sizeof(Coord) * meshExt->nodeLocalCount );
+ }
+ /* Else, it is a spherical mesh (construct extensions prevents otherwise), convert each one */
+ else {
+ Node_LocalIndex node_lI;
+
+ for( node_lI = 0; node_lI < meshExt->nodeLocalCount; node_lI++ ) {
+ Coord* spherical = &meshExt->initialNodeCoord[node_lI];
+ Coord* cartesian = &mesh->nodeCoord[node_lI];
+ double sqXsqY =
+ (*cartesian)[0] * (*cartesian)[0] +
+ (*cartesian)[1] * (*cartesian)[1];
+
+ /* At this point in time, spehrical coordinates are kept as radians, not degress as it evaluates faster */
+
+ /* r = sqrt( sq( x ) + sq( y ) + sq( z ) ) */
+ (*spherical)[1] = sqrt( sqXsqY + (*cartesian)[2] * (*cartesian)[2] );
+
+ /* phi = arcsin( sqrt( sq( x ) + sq( y ) ) / z ) */
+ (*spherical)[2] = asin( (*cartesian)[1] / (*spherical)[1] );
+
+ /* theta = arctan( y / x ) */
+ (*spherical)[0] = atan( (*cartesian)[0] / (*cartesian)[2] );
+
+ if( (*cartesian)[2] < 0.0 ) {
+ (*spherical)[0] += M_PI;
+ }
+ else if( (*cartesian)[0] < 0.0 ) {
+ (*spherical)[0] += 2 * M_PI;
+ }
+
+ if( (*spherical)[0] > M_PI )
+ (*spherical)[0] = -2.0 * M_PI + (*spherical)[0];
+ }
+ }
+
+ /* Obtain neighbour rank info */
+ _HexaMD_Shadow_BuildProcs( decomp, meshExt->neighbourRank );
+
+ /* Build local temporary sets of the global walls and top-internal shadow nodes */
+ gWallSet = (IndexSet**)malloc( sizeof(IndexSet*) * 6 );
+ gWallSet[0] = RegularMeshUtils_CreateGlobalLeftSet( mesh );
+ gWallSet[1] = RegularMeshUtils_CreateGlobalRightSet( mesh );
+ gWallSet[2] = RegularMeshUtils_CreateGlobalBottomSet( mesh );
+ gWallSet[3] = RegularMeshUtils_CreateGlobalBackSet( mesh );
+ gWallSet[4] = RegularMeshUtils_CreateGlobalFrontSet( mesh );
+ gWallSet[5] = RegularMeshUtils_CreateGlobalTopSet( mesh ); /* TODO: positive radial dir for cartesian */
+ shadowNodeSetLocal = (IndexSet**)malloc( sizeof(IndexSet*) * rnCount );
+ shadowNodeSetRemote = (IndexSet**)malloc( sizeof(IndexSet*) * rnCount );
+ shadowElementSetLocal = (IndexSet**)malloc( sizeof(IndexSet*) * rnCount );
+ shadowElementSetRemote = (IndexSet**)malloc( sizeof(IndexSet*) * rnCount );
+ for( rn_I = 0; rn_I < rnCount; rn_I++ ) {
+ shadowNodeSetLocal[rn_I] = IndexSet_New( mesh->nodeLocalCount );
+ shadowNodeSetRemote[rn_I] = IndexSet_New( mesh->nodeGlobalCount );
+ shadowElementSetLocal[rn_I] = IndexSet_New( mesh->elementLocalCount );
+ shadowElementSetRemote[rn_I] = IndexSet_New( mesh->elementGlobalCount );
+ }
+
+ /* Build the "wall", "topInternal" and "internal" local node sets, and the node shadow sets */
+ for( node_gI = 0; node_gI < meshExt->nodeGlobalCount; node_gI++ ) {
+ Node_LocalIndex node_lI;
+
+ node_lI = Mesh_NodeMapGlobalToLocal( mesh, node_gI );
+ if( node_lI < meshExt->nodeLocalCount ) {
+ if( IndexSet_IsMember( gWallSet[5], node_lI ) ) {
+ IndexSet_Add( meshExt->topInternalSet, node_lI );
+ /*dbPrint3(); fflush( stdout );
+
+ _SnacRemesher_CheckForShadowNode(
+ context,
+ contextExt,
+ node_gI,
+ node_lI,
+ ShadowNodeSetCurrent,
+ ShadowNodeSetLocal,
+ ShadowNodeSetRemote );*/
+ }
+ else if( IndexSet_IsMember( gWallSet[2], node_lI ) ) {
+ IndexSet_Add( meshExt->bottomInternalSet, node_lI );
+ /*dbPrint3_2(); fflush( stdout );
+
+ _SnacRemesher_CheckForShadowNode(
+ context,
+ contextExt,
+ node_gI,
+ node_lI,
+ ShadowNodeSetCurrent,
+ ShadowNodeSetLocal,
+ ShadowNodeSetRemote );*/
+ }
+ /* The walls (except for positive radial dir) remesh back to initial positions...
+ maintain as one local set */
+ else if(
+ IndexSet_IsMember( gWallSet[0], node_lI ) ||
+ IndexSet_IsMember( gWallSet[1], node_lI ) ||
+ IndexSet_IsMember( gWallSet[3], node_lI ) ||
+ IndexSet_IsMember( gWallSet[4], node_lI ) )
+ {
+ IndexSet_Add( meshExt->wallSet, node_lI );
+ /*dbPrint2();
+
+ _SnacRemesher_CheckForShadowNode(
+ context,
+ contextExt,
+ node_gI,
+ node_lI,
+ ShadowNodeSetCurrent,
+ ShadowNodeSetLocal,
+ ShadowNodeSetRemote );*/
+ }
+ /* The positive radial dir wall internal nodes are free...
+ maintain as one local set */
+
+ /* Internal nodes are interpolated in the radial dir...
+ maintain as one set */
+ else {
+ IndexSet_Add( meshExt->internalSet, node_lI );
+ }
+ }
+ else Journal_DPrintf( context->debug, "node_gI: %3u node_lI: %3u, not local\n", node_gI, node_lI );
+ }
+
+ /* Build the element shadow sets */
+ for( element_gI = 0; element_gI < meshExt->elementGlobalCount; element_gI++ ) {
+ Element_LocalIndex element_lI;
+ Element_GlobalIndex en_I;
+
+ element_lI = decomp->elementMapGlobalToLocal( decomp, element_gI );
+ if( element_lI < meshExt->elementLocalCount ) {
+ Element_GlobalIndex eNbrCnt;
+ eNbrCnt = eTopology->neighbourCount( eTopology, element_gI );
+ if( eNbrCnt ) {
+ Element_GlobalIndex* eNbrs;
+
+ eNbrs = (Element_GlobalIndex*)malloc( sizeof(Element_GlobalIndex) * eNbrCnt );
+ eTopology->buildNeighbours( eTopology, element_gI, eNbrs );
+
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Partition_Index rank;
+
+ rank = meshExt->neighbourRank[rn_I];
+
+ for( en_I = 0; en_I < eNbrCnt; en_I++ ) {
+ if( eNbrs[en_I] < meshExt->elementGlobalCount &&
+ IndexSet_IsMember( decomp->localElementSets[rank], eNbrs[en_I] ) &&
+ !IndexSet_IsMember(
+ decomp->localElementSets[context->rank],
+ eNbrs[en_I] ) )
+ {
+ IndexSet_Add( shadowElementSetRemote[rn_I], eNbrs[en_I] );
+ }
+ }
+ }
+
+ if( eNbrs )
+ free( eNbrs );
+ }
+ }
+ }
+
+ /* Resolve the "wall", "topInternal" and "internal" sets into array of indices (for speed) */
+ IndexSet_GetMembers( meshExt->wallSet, &meshExt->wallCount, &meshExt->wallArray );
+ IndexSet_GetMembers( meshExt->topInternalSet, &meshExt->topInternalCount, &meshExt->topInternalArray );
+ IndexSet_GetMembers( meshExt->bottomInternalSet, &meshExt->bottomInternalCount, &meshExt->bottomInternalArray );
+ IndexSet_GetMembers( meshExt->internalSet, &meshExt->internalCount, &meshExt->internalArray );
+
+ /* Build shadow tables and arrays */
+ meshExt->shadowNodeLocalCount = (Node_LocalIndex*)malloc( sizeof(Node_LocalIndex) * rnCount );
+ meshExt->shadowNodeLocalArray = (Node_LocalIndex**)malloc( sizeof(Node_LocalIndex*) * rnCount );
+ meshExt->shadowNodeRemoteCount = (Node_ShadowIndex*)malloc( sizeof(Node_ShadowIndex) * rnCount );
+ meshExt->shadowNodeRemoteArray = (Node_GlobalIndex**)malloc( sizeof(Node_GlobalIndex*) * rnCount );
+ meshExt->shadowNodeRemoteCoord = (Coord**)malloc( sizeof(Coord*) * rnCount );
+ meshExt->shadowNodeRemote = (Snac_Node**)malloc( sizeof(Snac_Node*) * rnCount );
+ meshExt->shadowElementLocalCount = (Element_LocalIndex*)malloc( sizeof(Element_LocalIndex) * rnCount );
+ meshExt->shadowElementLocalArray = (Element_LocalIndex**)malloc( sizeof(Element_LocalIndex*) * rnCount );
+ meshExt->shadowElementRemoteCount = (Element_ShadowIndex*)malloc( sizeof(Element_ShadowIndex) * rnCount );
+ meshExt->shadowElementRemoteArray = (Element_GlobalIndex**)malloc( sizeof(Element_GlobalIndex*) * rnCount );
+ meshExt->shadowElementRemote = (Snac_Element**)malloc( sizeof(Snac_Element*) * rnCount );
+ for( rn_I = 0; rn_I < rnCount; rn_I++ ) {
+ Element_LocalIndex e_lI;
+ Node_LocalIndex n_lI;
+ MPI_Status status;
+ Element_ShadowIndex se_I;
+
+ /* temp */
+ meshExt->shadowNodeLocalCount[rn_I] = 0;
+ meshExt->shadowNodeRemoteCount[rn_I] = 0;
+
+ /* convert shadow elements to arrays */
+ IndexSet_GetMembers(
+ shadowElementSetRemote[rn_I],
+ &meshExt->shadowElementRemoteCount[rn_I],
+ &meshExt->shadowElementRemoteArray[rn_I] );
+ /* transfer to neighbours - send size */
+ MPI_Send(
+ &meshExt->shadowElementRemoteCount[rn_I],
+ 1,
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 0,
+ decomp->communicator );
+ /* send data */
+ MPI_Send(
+ meshExt->shadowElementRemoteArray[rn_I],
+ meshExt->shadowElementRemoteCount[rn_I],
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 7,
+ decomp->communicator );
+ /* recv size */
+ MPI_Recv(
+ &meshExt->shadowElementLocalCount[rn_I],
+ 1,
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 0,
+ decomp->communicator,
+ &status );
+ meshExt->shadowElementLocalArray[rn_I] = (Index*)malloc(
+ sizeof(Element_LocalIndex) * meshExt->shadowElementLocalCount[rn_I] );
+ /* recv data */
+ MPI_Recv(
+ meshExt->shadowElementLocalArray[rn_I],
+ meshExt->shadowElementLocalCount[rn_I],
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 7,
+ decomp->communicator,
+ &status );
+ /* loop over data and convert to local indices */
+ for( e_lI = 0; e_lI < meshExt->shadowElementLocalCount[rn_I]; e_lI++ ) {
+ Index element_lI = Mesh_ElementMapGlobalToLocal( mesh, meshExt->shadowElementLocalArray[rn_I][e_lI] );
+
+ if( element_lI >= meshExt->elementLocalCount )
+ assert( 0 ); /* Big trouble */
+
+ meshExt->shadowElementLocalArray[rn_I][e_lI] = element_lI;
+ }
+ /* setup the remaining element info */
+ meshExt->shadowElementRemote[rn_I] = (Snac_Element*)ExtensionManager_Malloc(
+ mesh->elementExtensionMgr,
+ meshExt->shadowElementRemoteCount[rn_I] );
+ ExtensionManager_Memset(
+ mesh->elementExtensionMgr,
+ meshExt->shadowElementRemote[rn_I],
+ 0,
+ meshExt->shadowElementRemoteCount[rn_I] );
+
+ /* Loop over shadow elements to calculate node info */
+ for( se_I = 0; se_I < meshExt->shadowElementRemoteCount[rn_I]; se_I++ ) {
+ NodeLayout* nodeLayout = mesh->layout->nodeLayout;
+ Index sen_I, seNodeCnt;
+ Index* seNodes;
+
+ /* extract nodes */
+ seNodeCnt = nodeLayout->elementNodeCount( nodeLayout, meshExt->shadowElementRemoteArray[rn_I][se_I] );
+ seNodes = (Index*)malloc( sizeof(Index) * seNodeCnt );
+ nodeLayout->buildElementNodes( nodeLayout, meshExt->shadowElementRemoteArray[rn_I][se_I], seNodes );
+
+ for( sen_I = 0; sen_I < seNodeCnt; sen_I++ ) {
+ Index localNode = Mesh_NodeMapGlobalToLocal( mesh, seNodes[sen_I] );
+
+ if( localNode >= meshExt->nodeLocalCount ) {
+ IndexSet_Add( shadowNodeSetRemote[rn_I], seNodes[sen_I] );
+ }
+ }
+
+ if( seNodes )
+ free( seNodes );
+ }
+ /* convert to array */
+ IndexSet_GetMembers(
+ shadowNodeSetRemote[rn_I],
+ &meshExt->shadowNodeRemoteCount[rn_I],
+ &meshExt->shadowNodeRemoteArray[rn_I] );
+ /* transfer to neighbours - send size */
+ MPI_Send(
+ &meshExt->shadowNodeRemoteCount[rn_I],
+ 1,
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 0,
+ decomp->communicator );
+ /* send data */
+ MPI_Send(
+ meshExt->shadowNodeRemoteArray[rn_I],
+ meshExt->shadowNodeRemoteCount[rn_I],
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 7,
+ decomp->communicator );
+ /* recv size */
+ MPI_Recv(
+ &meshExt->shadowNodeLocalCount[rn_I],
+ 1,
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 0,
+ decomp->communicator,
+ &status );
+ meshExt->shadowNodeLocalArray[rn_I] = (Index*)malloc( sizeof(Index) * meshExt->shadowNodeLocalCount[rn_I] );
+ /* recv data */
+ MPI_Recv(
+ meshExt->shadowNodeLocalArray[rn_I],
+ meshExt->shadowNodeLocalCount[rn_I],
+ MPI_INT,
+ meshExt->neighbourRank[rn_I],
+ 7,
+ decomp->communicator,
+ &status );
+ /* loop over data and convert to local indices */
+ for( n_lI = 0; n_lI < meshExt->shadowNodeLocalCount[rn_I]; n_lI++ ) {
+ Index node_lI = Mesh_NodeMapGlobalToLocal( mesh, meshExt->shadowNodeLocalArray[rn_I][n_lI] );
+
+ if( node_lI >= meshExt->nodeLocalCount )
+ assert( 0 ); /* something is terribly wrong */
+
+ meshExt->shadowNodeLocalArray[rn_I][n_lI] = node_lI;
+ }
+ /* setup remaining node info */
+ meshExt->shadowNodeRemoteCoord[rn_I] = (Coord*)malloc( sizeof(Coord) * meshExt->shadowNodeRemoteCount[rn_I] );
+ memset( meshExt->shadowNodeRemoteCoord[rn_I], 0, sizeof(Coord) * meshExt->shadowNodeRemoteCount[rn_I] );
+ meshExt->shadowNodeRemote[rn_I] = (Snac_Node*)ExtensionManager_Malloc(
+ mesh->nodeExtensionMgr,
+ meshExt->shadowNodeRemoteCount[rn_I] );
+ ExtensionManager_Memset( mesh->nodeExtensionMgr, meshExt->shadowNodeRemote[rn_I], 0, meshExt->shadowNodeRemoteCount[rn_I] );
+ }
+
+ /* Delete temporary sets */
+ for( rn_I = 0; rn_I < rnCount; rn_I++ ) {
+ Stg_Class_Delete( shadowElementSetRemote[rn_I] );
+ Stg_Class_Delete( shadowElementSetLocal[rn_I] );
+ Stg_Class_Delete( shadowNodeSetRemote[rn_I] );
+ Stg_Class_Delete( shadowNodeSetLocal[rn_I] );
+ }
+ free( shadowElementSetRemote );
+ free( shadowElementSetLocal );
+ free( shadowNodeSetRemote );
+ free( shadowNodeSetLocal );
+ Stg_Class_Delete( gWallSet[5] );
+ Stg_Class_Delete( gWallSet[4] );
+ Stg_Class_Delete( gWallSet[3] );
+ Stg_Class_Delete( gWallSet[2] );
+ Stg_Class_Delete( gWallSet[1] );
+ Stg_Class_Delete( gWallSet[0] );
+ free( gWallSet );
+}
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/InitialConditions.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,47 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: InitialConditions.h 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_InitialConditions_h__
+#define __SnacRemesher_InitialConditions_h__
+
+
+ void _SnacRemesher_InitialConditions( void* _context, void* data );
+
+
+#endif /* __SnacRemesher_InitialConditions_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Make.mm
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Make.mm (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Make.mm 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,67 @@
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+##
+## Copyright (C), 2003,
+## Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+## Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+## University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+##
+## Authors:
+## Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+## Stevan M. Quenette, Visitor in Geophysics, Caltech.
+## Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+## Luc Lavier, Research Scientist, Caltech.
+##
+## 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## $Id: Make.mm 2921 2005-05-10 06:44:06Z EunseoChoi $
+##
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+include Makefile.def
+
+PROJECT = Snac
+PACKAGE = ${def_mod}module
+
+PROJ_LIB = $(BLD_LIBDIR)/$(PACKAGE).a
+PROJ_DLL = $(BLD_LIBDIR)/$(PACKAGE).$(EXT_SO)
+PROJ_TMPDIR = $(BLD_TMPDIR)/$(PROJECT)/$(PACKAGE)
+PROJ_CLEAN += $(PROJ_LIB) $(PROJ_DLL)
+PROJ_INCDIR = $(BLD_INCDIR)/${def_inc}
+
+PROJ_SRCS = ${def_srcs}
+PROJ_CC_FLAGS += -I$(BLD_INCDIR)/$(PROJECT) -I$(BLD_INCDIR)/Snac -I$(BLD_INCDIR)/StGermain -I$(STGERMAIN_INCDIR)/ -I$(STGERMAIN_INCDIR)/StGermain `xml2-config --cflags` -DCURR_MODULE_NAME=\"${def_mod}\"
+PROJ_LIBRARIES = -L$(BLD_LIBDIR) -L$(STGERMAIN_LIBDIR)/ -lSnac -lStGermain `xml2-config --libs` $(MPI_LIBPATH) $(MPI_LIBS)
+LCCFLAGS =
+
+# I keep file lists to build a monolith .so from a set of .a's
+PROJ_OBJS_IN_TMP = ${addprefix $(PROJECT)/$(PACKAGE)/, ${addsuffix .o, ${basename $(PROJ_SRCS)}}}
+PROJ_OBJLIST = $(BLD_TMPDIR)/$(PROJECT).$(PACKAGE).objlist
+
+all: $(PROJ_LIB) DLL createObjList export
+
+DLL: product_dirs $(PROJ_OBJS)
+ $(CC) -o $(PROJ_DLL) $(PROJ_OBJS) $(COMPILER_LCC_SOFLAGS) $(LCCFLAGS) $(PROJ_LIBRARIES) $(EXTERNAL_LIBPATH) $(EXTERNAL_LIBS)
+
+
+
+createObjList::
+ @echo ${PROJ_OBJS_IN_TMP} | cat > ${PROJ_OBJLIST}
+
+#export:: export-headers
+export:: export-headers export-libraries
+EXPORT_HEADERS = ${def_hdrs}
+EXPORT_LIBS = $(PROJ_LIB) $(PROJ_DLL)
+
+check::
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Makefile.def
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Makefile.def (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Makefile.def 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,68 @@
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+##
+## Copyright (C), 2003,
+## Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+## Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+## University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+##
+## Authors:
+## Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+## Stevan M. Quenette, Visitor in Geophysics, Caltech.
+## Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+## Luc Lavier, Research Scientist, Caltech.
+## Luc Lavier, Caltech.
+##
+## 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## $Id: Makefile.def 3095 2005-07-13 09:50:46Z LukeHodkinson $
+##
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+def_mod = SnacRemesher
+def_inc = Snac/Remesher
+
+def_srcs = \
+ Utils.c \
+ EntryPoint.c \
+ Context.c \
+ Mesh.c \
+ Register.c \
+ ConstructExtensions.c \
+ Build.c \
+ InitialConditions.c \
+ Output.c \
+ TestCondFunc.c \
+ Remesh.c \
+ RemeshCoords.c \
+ RemeshNodes.c \
+ RemeshElements.c \
+ DeleteExtensions.c
+
+def_hdrs = \
+ types.h \
+ Utils.h \
+ Context.h \
+ EntryPoint.h \
+ Mesh.h \
+ Register.h \
+ ConstructExtensions.h \
+ Build.h \
+ InitialConditions.h \
+ Output.h \
+ TestCondFunc.h \
+ Remesh.h \
+ DeleteExtensions.h \
+ Remesher.h
+
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,228 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Mesh.c 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+
+#include <stdio.h>
+
+
+/*
+** Due to the rewrite this func is severely useless. Need to fix it.
+*/
+
+void SnacRemesher_Mesh_Print( void* mesh, Stream* stream ) {
+ SnacRemesher_Mesh* self = (SnacRemesher_Mesh*)mesh;
+/* Node_LocalIndex node_lI; */
+/* Node_LocalIndex index; */
+
+ Journal_Printf( stream, "SnacRemesher_Mesh:\n" );
+
+#if 0
+ Journal_Printf( stream, "\tnodeLocalCount: %u\n", self->nodeLocalCount );
+ Journal_Printf( stream, "\tnodeDomainCount: %u\n", self->nodeDomainCount );
+ Journal_Printf( stream, "\tnodeGlobalCount: %u\n", self->nodeGlobalCount );
+ Journal_Printf( stream, "\telementLocalCount: %u\n", self->elementLocalCount );
+ Journal_Printf( stream, "\telementDomainCount: %u\n", self->elementDomainCount );
+ Journal_Printf( stream, "\telementGlobalCount: %u\n", self->elementGlobalCount );
+ Journal_Printf( stream, "\tinitialNodeCoord[0-%u]: { ", self->nodeLocalCount );
+ for( node_lI = 0; node_lI < self->nodeLocalCount; node_lI++ ) {
+ Journal_Printf( stream,
+ "{ %g, %g, %g } ",
+ self->initialNodeCoord[node_lI][0],
+ self->initialNodeCoord[node_lI][1],
+ self->initialNodeCoord[node_lI][2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tnewNodeCoord[0-%u]: { ", self->nodeLocalCount );
+ for( node_lI = 0; node_lI < self->nodeLocalCount; node_lI++ ) {
+ Journal_Printf( stream,
+ "{ %g, %g, %g } ",
+ self->newNodeCoord[node_lI][0],
+ self->newNodeCoord[node_lI][1],
+ self->newNodeCoord[node_lI][2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tnewNode[0-%u]: { ... TODO: Print nodes nicely... }\n", self->nodeLocalCount );
+
+ Journal_Printf( stream,
+ "\tmeshType: %s\n",
+ self->meshType == SnacRemesher_Spherical ? "Spherical" :
+ self->meshType == SnacRemesher_Cartesian ? "Cartesian" : "Invalid value!" );
+
+ Journal_Printf( stream, "\tneighbourRankCount: %u\n", self->neighbourRankCount );
+ Journal_Printf( stream, "\tneighbourRank[0-%u]: {", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Journal_Printf( stream, "%i ", self->neighbourRank[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+
+ Journal_Printf( stream, "\ttopInternalSet: " ); Print( self->topInternalSet, stream );
+ Journal_Printf( stream, "\tbottomInternalSet: " ); Print( self->bottomInternalSet, stream );
+ Journal_Printf( stream, "\twallSet: " ); Print( self->wallSet, stream );
+ Journal_Printf( stream, "\tinternalSet: " ); Print( self->internalSet, stream );
+
+ Journal_Printf( stream, "\ttopInternalCount: %u\n", self->topInternalCount );
+ Journal_Printf( stream, "\tbottomInternalCount: %u\n", self->bottomInternalCount );
+ Journal_Printf( stream, "\twalllCount: %u\n", self->wallCount );
+ Journal_Printf( stream, "\tinternalCount: %u\n", self->internalCount );
+
+ Journal_Printf( stream, "\ttopInternalArray[0-%u]: { ", self->topInternalCount );
+ for( index = 0; index < self->topInternalCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->topInternalArray[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tbottomInternalArray[0-%u]: { ", self->bottomInternalCount );
+ for( index = 0; index < self->bottomInternalCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->bottomInternalArray[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\twallSet[0-%u]: { ", self->wallCount );
+ for( index = 0; index < self->wallCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->wallArray[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tinternalArray[0-%u]: { ", self->internalCount );
+ for( index = 0; index < self->internalCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->internalArray[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+
+ /* Shadow */
+ Journal_Printf( stream, "\tshadowNodeLocalCount[0-%u]: { ", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->shadowNodeLocalCount[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowNodeLocalArray[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowNodeLocalArray[%u][0-%u]: { ", index, self->shadowNodeLocalCount[index] );
+ for( index2 = 0; index2 < self->shadowNodeLocalCount[index]; index2++ ) {
+ Journal_Printf( stream, "%u ", self->shadowNodeLocalArray[index][index2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowNodeRemoteCount[0-%u]: { ", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->shadowNodeRemoteCount[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowNodeRemoteArray[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowNodeRemoteArray[%u][0-%u]: { ", index, self->shadowNodeRemoteCount[index] );
+ for( index2 = 0; index2 < self->shadowNodeRemoteCount[index]; index2++ ) {
+ Journal_Printf( stream, "%u ", self->shadowNodeRemoteArray[index][index2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowNodeRemoteCoord[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowNodeRemoteCoord[%u][0-%u]: { ", index, self->shadowNodeRemoteCount[index] );
+ for( index2 = 0; index2 < self->shadowNodeRemoteCount[index]; index2++ ) {
+ Journal_Printf( stream,
+ "{ %g, %g, %g }, ",
+ self->shadowNodeRemoteCoord[index][index2][0],
+ self->shadowNodeRemoteCoord[index][index2][1],
+ self->shadowNodeRemoteCoord[index][index2][2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowNodeRemote[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowNodeRemote[%u][0-%u]: { ", index, self->shadowNodeRemoteCount[index] );
+ for( index2 = 0; index2 < self->shadowNodeRemoteCount[index]; index2++ ) {
+ Snac_Node_Print( &self->shadowNodeRemote[index][index2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+
+ /* Shadow Elements*/
+ Journal_Printf( stream, "\tshadowElementLocalCount[0-%u]: { ", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->shadowElementLocalCount[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowElementLocalArray[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowElementLocalArray[%u][0-%u]: { ", index, self->shadowElementLocalCount[index] );
+ for( index2 = 0; index2 < self->shadowElementLocalCount[index]; index2++ ) {
+ Journal_Printf( stream, "%u ", self->shadowElementLocalArray[index][index2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowElementRemoteCount[0-%u]: { ", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Journal_Printf( stream, "%u ", self->shadowElementRemoteCount[index] );
+ }
+ Journal_Printf( stream, "}\n" );
+ Journal_Printf( stream, "\tshadowElementRemoteArray[0-%u]: {\n", self->neighbourRankCount );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowElementRemoteArray[%u][0-%u]: { ", index, self->shadowElementRemoteCount[index] );
+ for( index2 = 0; index2 < self->shadowElementRemoteCount[index]; index2++ ) {
+ Journal_Printf( stream, "%u ", self->shadowElementRemoteArray[index][index2] );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+ for( index = 0; index < self->neighbourRankCount; index++ ) {
+ Index index2;
+
+ Journal_Printf( stream, "\t\tshadowElementRemote[%u][0-%u]: { ", index, self->shadowElementRemoteCount[index] );
+ for( index2 = 0; index2 < self->shadowElementRemoteCount[index]; index2++ ) {
+ Snac_Element_Print( &self->shadowElementRemote[index][index2], stream );
+ }
+ Journal_Printf( stream, "}\n" );
+ }
+ Journal_Printf( stream, "}\n" );
+#endif
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Mesh.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,173 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+** Snac exchanger properties extensions to the mesh construct.
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Mesh.h 3173 2005-11-21 23:47:09Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Mesh_h__
+#define __SnacRemesher_Mesh_h__
+
+
+ typedef enum {
+ SnacRemesher_Spherical,
+ SnacRemesher_Cartesian,
+ SnacRemesher_MeshTypeMax
+ } SnacRemesher_MeshType;
+
+ struct _SnacRemesher_ElementBarcord {
+ double L[4];
+ Element_DomainIndex elnum;
+ Tetrahedra_Index tetnum;
+ };
+ typedef struct _SnacRemesher_ElementBarcord SnacRemesher_ElementBarcord;
+
+ struct _SnacRemesher_ElementBarcoef {
+ /* Each of 5 tet has 4 shape functions (i.e., 4 nodes),
+ each of which needs 4 coefficients. */
+ double coef[5][4][4];
+ };
+ typedef struct _SnacRemesher_ElementBarcoef SnacRemesher_ElementBarcoef;
+
+ /* Mesh Information */
+ struct _SnacRemesher_Mesh {
+ SnacRemesher_MeshType meshType;
+
+ /* A placeholder for new coords, and stores static node coords. */
+ Coord* newNodeCoords;
+ Snac_Node* newNodes;
+ Coord* oldBarycenters;
+ Coord* newBarycenters;
+ SnacRemesher_ElementBarcord* barcord;
+ SnacRemesher_ElementBarcoef* barcoef;
+
+ Snac_Element* newElements;
+
+ /* If during the remesh nodes are found outside the old mesh they will be stored here. */
+ unsigned nExternalNodes;
+ Node_LocalIndex* externalNodes;
+ unsigned nExternalElements;
+ Element_LocalIndex* externalElements;
+
+ /* Used for interpolating top/bottom internal nodes. */
+ unsigned nTopInternNodes;
+ Node_LocalIndex* topInternToLocal;
+ unsigned nBotInternNodes;
+ Node_LocalIndex* botInternToLocal;
+
+ unsigned nTopTriNodes;
+ Node_DomainIndex* topTriToDomain;
+ unsigned nBotTriNodes;
+ Node_DomainIndex* botTriToDomain;
+
+ /* Used for interpolating bulk nodes. */
+ unsigned nYLines;
+ unsigned* yLineLTerm;
+ unsigned* yLineUTerm;
+ unsigned* yLineNYInds;
+ unsigned** yLineYInds;
+ Node_LocalIndex** yLineLocalInds;
+
+ /* The sync class provides remote terminals for interpolating bulk nodes. */
+ SnacSync* sync;
+ };
+
+
+#if 0
+ /* Mesh Information */
+ struct _SnacRemesher_Mesh {
+
+ Coord* initialNodeCoord; /* Array of initial node coordinates */
+ Coord* newNodeCoord; /* Array of new/temporary node coordinates */
+ Snac_Node* newNode; /* Array of new/temporary node values */
+ Snac_Element* newElement; /* Array of new Elements */
+
+ /* Node count... may not otherwise be directly available from this structure, so we keep a copy here */
+ Node_LocalIndex nodeLocalCount;
+ Node_DomainIndex nodeDomainCount;
+ Node_GlobalIndex nodeGlobalCount;
+ Element_LocalIndex elementLocalCount;
+ Element_DomainIndex elementDomainCount;
+ Element_GlobalIndex elementGlobalCount;
+
+ /* Mesh type */
+ SnacRemesher_MeshType meshType;
+
+ /* Rank neighbour info */
+ Partition_Index neighbourRankCount;
+ Partition_Index* neighbourRank;
+
+ /* The walls (except for positive radial dir) remesh back to initial positions... maintain as one local set */
+ IndexSet* wallSet;
+ Index wallCount;
+ Index* wallArray; /* content is local indices */
+
+ /* The positive radial dir wall internal nodes are free... maintain as one local set */
+ IndexSet* topInternalSet;
+ Index topInternalCount;
+ Index* topInternalArray;
+
+ /* The positive radial dir wall internal nodes are free... maintain as one local set */
+ IndexSet* bottomInternalSet;
+ Index bottomInternalCount;
+ Index* bottomInternalArray;
+
+ /* Internal nodes are interpolated in the radial dir... maintain as one set */
+ IndexSet* internalSet;
+ Index internalCount;
+ Index* internalArray; /* content is local indices */
+
+ /* Shadow node tables */
+ Node_LocalIndex* shadowNodeLocalCount;
+ Node_LocalIndex** shadowNodeLocalArray;
+ Node_ShadowIndex* shadowNodeRemoteCount;
+ Node_LocalIndex** shadowNodeRemoteArray;
+ Coord** shadowNodeRemoteCoord;
+ Snac_Node** shadowNodeRemote;
+ Element_LocalIndex* shadowElementLocalCount;
+ Element_LocalIndex** shadowElementLocalArray;
+ Element_ShadowIndex* shadowElementRemoteCount;
+ Element_GlobalIndex** shadowElementRemoteArray;
+ Snac_Element** shadowElementRemote;
+ };
+#endif
+
+ /* Print the contents of a mesh */
+ void SnacRemesher_Mesh_Print( void* mesh, Stream* stream );
+
+
+#endif /* __SnacRemesher_Mesh_h__ */
+
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,79 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Output.c 1095 2004-03-28 00:51:42Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Output.h"
+#include "Context.h"
+#include "Register.h"
+#include <stdio.h>
+
+void _SnacRemesher_DumpInfo( void* _context ) {
+ Snac_Context* context = (Snac_Context*) _context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ char cr[255];
+
+ if( context->rank != 0)
+ return;
+
+ switch( contextExt->condition ) {
+ case SnacRemesher_OnTimeStep:
+ sprintf(cr,"OnTimeStep");
+ break;
+ case SnacRemesher_OnMinLengthScale:
+ sprintf(cr,"OnMinLengthScale");
+ break;
+ case SnacRemesher_OnBothTimeStepLength:
+ sprintf(cr,"OnBothTimeStepLength");
+ break;
+ case SnacRemesher_Off:
+ sprintf(cr,"Off");
+ break;
+ }
+
+ fprintf( contextExt->remesherOut, "%6u: %s %6d %6u %12g %12g %12g %12g\n",
+ (long unsigned int)contextExt->remeshingCount,
+ cr,
+ context->timeStep,
+ (long unsigned int)contextExt->OnTimeStep,
+ contextExt->onMinLengthScale,
+ context->minLengthScale/context->initMinLengthScale,
+ context->minLengthScale,context->initMinLengthScale);
+ fflush( contextExt->remesherOut );
+
+}
+
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Output.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,37 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Output.h 1095 2004-03-28 00:51:42Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef _SnacRemesher_Output_
+#define _SnacRemesher_Output_
+
+ void _SnacRemesher_DumpInfo( void* _context );
+
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,145 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Register.c 3243 2006-10-12 09:04:00Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+#include "Context.h"
+#include "Mesh.h"
+#include "ConstructExtensions.h"
+#include "Build.h"
+#include "InitialConditions.h"
+#include "Remesh.h"
+#include "DeleteExtensions.h"
+#include "Register.h"
+#include <stdio.h>
+
+/* Textual name of this class */
+const Type SnacRemesher_Type = "SnacRemesher";
+
+ExtensionInfo_Index SnacRemesher_ContextHandle;
+ExtensionInfo_Index SnacRemesher_MeshHandle;
+
+const Name SnacRemesher_EP_InterpolateNode = "SnacRemesher_EP_InterpolateNode";
+const Name SnacRemesher_EP_InterpolateElement = "SnacRemesher_EP_InterpolateElement";
+
+
+Index _SnacRemesher_Register( PluginsManager* pluginsMgr ) {
+ return PluginsManager_Submit( pluginsMgr,
+ SnacRemesher_Type,
+ "0",
+ _SnacRemesher_DefaultNew );
+}
+
+
+void* _SnacRemesher_DefaultNew( Name name ) {
+ return _Codelet_New( sizeof(Codelet),
+ SnacRemesher_Type,
+ _Codelet_Delete,
+ _Codelet_Print,
+ _Codelet_Copy,
+ _SnacRemesher_DefaultNew,
+ _SnacRemesher_Construct,
+ _Codelet_Build,
+ _Codelet_Initialise,
+ _Codelet_Execute,
+ _Codelet_Destroy,
+ name );
+}
+
+
+void _SnacRemesher_Construct( void* component, Stg_ComponentFactory* cf, void* data ) {
+ Snac_Context* context;
+
+ /* Retrieve context. */
+ context = (Snac_Context*)Stg_ComponentFactory_ConstructByName( cf, "context", Snac_Context, True, data );
+
+ Journal_Printf( context->debug, "In: %s\n", __func__ );
+
+ /* Add extensions to nodes, elements and the context */
+ SnacRemesher_ContextHandle = ExtensionManager_Add(
+ context->extensionMgr,
+ SnacRemesher_Type,
+ sizeof(SnacRemesher_Context) );
+ SnacRemesher_MeshHandle = ExtensionManager_Add(
+ context->meshExtensionMgr,
+ SnacRemesher_Type,
+ sizeof(SnacRemesher_Mesh) );
+
+ Journal_Printf( context->debug, "\tcontext extension handle: %u\n", SnacRemesher_ContextHandle );
+ Journal_Printf( context->debug, "\tmesh extension handle: %u\n", SnacRemesher_MeshHandle );
+
+ /* Register new entry points to the context (which manages them) */
+ Context_AddEntryPoint(
+ context,
+ SnacRemesher_EntryPoint_New( SnacRemesher_EP_InterpolateNode, SnacRemesher_InterpolateNode_CastType ) );
+ Context_AddEntryPoint(
+ context,
+ SnacRemesher_EntryPoint_New( SnacRemesher_EP_InterpolateElement, SnacRemesher_InterpolateElement_CastType ) );
+
+ /* Add extensions to the entry points */
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, AbstractContext_EP_Build ),
+ SnacRemesher_Type,
+ _SnacRemesher_Build,
+ SnacRemesher_Type );
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, AbstractContext_EP_Initialise ),
+ SnacRemesher_Type,
+ _SnacRemesher_InitialConditions,
+ SnacRemesher_Type );
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, AbstractContext_EP_Sync ),
+ SnacRemesher_Type,
+ _SnacRemesher_Remesh,
+ SnacRemesher_Type );
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, SnacRemesher_EP_InterpolateNode ),
+ SnacRemesher_Type,
+ _SnacRemesher_InterpolateNode,
+ SnacRemesher_Type );
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, SnacRemesher_EP_InterpolateElement ),
+ SnacRemesher_Type,
+ _SnacRemesher_InterpolateElement,
+ SnacRemesher_Type );
+ EntryPoint_Append(
+ Context_GetEntryPoint( context, AbstractContext_EP_DestroyExtensions ),
+ SnacRemesher_Type,
+ _SnacRemesher_DeleteExtensions,
+ SnacRemesher_Type );
+
+ /* Construct. */
+ _SnacRemesher_ConstructExtensions( context, data );
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Register.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,60 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Register.h 3243 2006-10-12 09:04:00Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Register_h__
+#define __SnacRemesher_Register_h__
+
+ /* Textual name of this class */
+ extern const Type SnacRemesher_Type;
+
+ /* Handles to extensions for quicker access */
+ extern ExtensionInfo_Index SnacRemesher_ContextHandle;
+ extern ExtensionInfo_Index SnacRemesher_MeshHandle;
+
+ /* Names to new entry points */
+ extern const Name SnacRemesher_EP_InterpolateNode;
+ extern const Name SnacRemesher_EP_InterpolateElement;
+
+ Index _SnacRemesher_Register( PluginsManager* pluginsMgr );
+
+ void* _SnacRemesher_DefaultNew( Name name );
+
+ void _SnacRemesher_Construct( void* component, Stg_ComponentFactory* cf, void* data );
+
+#endif /* __SnacRemesher_Register_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,326 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Pururav Thoutireddy,
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Pururav Thoutireddy, Staff Scientist, Caltech
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Remesh.c 3096 2005-07-13 23:51:01Z EunseoChoi $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Remesh.h"
+#include "Register.h"
+#include "Utils.h"
+#include "Output.h"
+
+#include <string.h>
+#include <assert.h>
+
+
+void _SnacRemesher_Remesh( void* _context, void* data ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Bool remesh;
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ switch( contextExt->condition ) {
+ case SnacRemesher_OnTimeStep:
+ /* Remeshing on multiples of "OnTimeStep", but don't remesh on loop 0. */
+ Journal_Firewall( contextExt->OnTimeStep, context->snacError,
+ "Invalid remesh timestep criterion." );
+ remesh = (context->timeStep <= 1) ? False :
+ (context->timeStep % contextExt->OnTimeStep == 0) ? True : False;
+ break;
+
+ case SnacRemesher_OnMinLengthScale:
+ remesh = (context->minLengthScale/context->initMinLengthScale <
+ contextExt->onMinLengthScale) ? True : False;
+ break;
+
+ case SnacRemesher_OnBothTimeStepLength:
+ Journal_Firewall( contextExt->OnTimeStep, context->snacError,
+ "Invalid remesh timestep criterion." );
+ remesh = (context->timeStep <= 1) ? False :
+ (context->timeStep % contextExt->OnTimeStep == 0) ? True : False;
+ remesh = remesh ? True : (context->minLengthScale/context->initMinLengthScale <
+ contextExt->onMinLengthScale) ? True : False;
+ break;
+
+ case SnacRemesher_Off:
+ default:
+ remesh = False;
+ break;
+ }
+
+ if( remesh ) {
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ Node_LocalIndex newNode_i;
+
+ Journal_Printf( context->snacInfo, "Remeshing!\n" );
+
+ /*
+ ** If spherical coordinates are being used,
+ ** then we'll need to convert the current mesh's cartesian coordinates
+ ** to spherical coordinates first.
+ */
+
+ if( meshExt->meshType == SnacRemesher_Spherical ) {
+ Node_LocalIndex lNode_i;
+
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ double x = mesh->nodeCoord[lNode_i][0];
+ double y = mesh->nodeCoord[lNode_i][1];
+ double z = mesh->nodeCoord[lNode_i][2];
+
+ mesh->nodeCoord[lNode_i][0] = SnacArcTan( y, x );
+ mesh->nodeCoord[lNode_i][1] = sqrt( x * x + y * y + z * z );
+ mesh->nodeCoord[lNode_i][2] = acos( z / meshExt->newNodeCoords[lNode_i][1] );
+ }
+ }
+
+ /* Sync the mesh. */
+ if( mesh->layout->decomp->procsInUse > 1 ) {
+ Mesh_Sync( mesh );
+ }
+
+ /* Remesh the coordinates. */
+ _SnacRemesher_NewCoords( context );
+
+ /* Interpolate current nodal values onto new coordinates. */
+ meshExt->newNodes = (Snac_Node*)ExtensionManager_Malloc( mesh->nodeExtensionMgr, mesh->nodeLocalCount );
+ _SnacRemesher_InterpolateNodes( context );
+
+ /* Don't forget the residualFr/Ft: This simple copy works because bottoms nodes are always bottom and remeshing doesn't change the node number. */
+ for( newNode_i = 0; newNode_i < mesh->nodeLocalCount; newNode_i++ ) {
+ Snac_Node* dstNode =
+ (Snac_Node*)ExtensionManager_At( context->mesh->nodeExtensionMgr,
+ meshExt->newNodes,
+ newNode_i );
+
+ Snac_Node* srcNode =
+ Snac_Node_At( context, newNode_i );
+
+ dstNode->residualFr = srcNode->residualFr;
+ dstNode->residualFt = srcNode->residualFt;
+ }
+
+ /* Interpolate current elemental values onto new coordinates. */
+ meshExt->oldBarycenters = Memory_Alloc_Array( Coord, mesh->elementDomainCount, "SnacRemesher" );
+ meshExt->newBarycenters = Memory_Alloc_Array( Coord, mesh->elementLocalCount, "SnacRemesher" );
+ meshExt->barcoef = Memory_Alloc_Array( SnacRemesher_ElementBarcoef, mesh->elementDomainCount, "SnacRemesher" );
+ meshExt->barcord = Memory_Alloc_Array( SnacRemesher_ElementBarcord, mesh->elementLocalCount, "SnacRemesher" );
+ meshExt->newElements = (Snac_Element*)ExtensionManager_Malloc( mesh->elementExtensionMgr, mesh->elementLocalCount );
+
+ /* Do the linear interpolation between grids of barycenters. */
+ _SnacRemesher_InterpolateElements( context );
+
+ /* Copy accross the new coord, node & element information to the current arrays. */
+ memcpy( mesh->nodeCoord, meshExt->newNodeCoords, mesh->nodeLocalCount * sizeof(Coord) );
+ memcpy( mesh->node, meshExt->newNodes, mesh->nodeExtensionMgr->finalSize * mesh->nodeLocalCount );
+ memcpy( mesh->element, meshExt->newElements, mesh->elementExtensionMgr->finalSize * mesh->elementLocalCount );
+
+ /* Update element attributes based on the new coordinates and the transferred variables. */
+ _SnacRemesher_UpdateElements( context );
+
+ /* Free some space, as it won't be needed until the next remesh. */
+ Memory_Free( meshExt->oldBarycenters );
+ Memory_Free( meshExt->newBarycenters );
+ Memory_Free( meshExt->barcoef );
+ Memory_Free( meshExt->barcoef );
+ ExtensionManager_Free( mesh->nodeExtensionMgr, meshExt->newNodes );
+ ExtensionManager_Free( mesh->elementExtensionMgr, meshExt->newElements );
+ meshExt->newNodes = NULL;
+ meshExt->newElements = NULL;
+
+ /*
+ ** If in spherical mode, convert back to cartesian coordinates.
+ */
+
+ if( meshExt->meshType == SnacRemesher_Spherical ) {
+ unsigned lNode_i;
+
+ for( lNode_i = 0; lNode_i < mesh->nodeLocalCount; lNode_i++ ) {
+ double theta = mesh->nodeCoord[lNode_i][0];
+ double r = mesh->nodeCoord[lNode_i][1];
+ double phi = mesh->nodeCoord[lNode_i][2];
+
+ mesh->nodeCoord[lNode_i][0] = r * sin( phi ) * cos( theta );
+ mesh->nodeCoord[lNode_i][1] = r * sin( phi ) * sin( theta );
+ mesh->nodeCoord[lNode_i][2] = r * cos( phi );
+ }
+ }
+
+ /* Sync the mesh. */
+ if( mesh->layout->decomp->procsInUse > 1 ) {
+ Mesh_Sync( mesh );
+ }
+
+ /* dump info such as remeshing frequency, criterion, and the current time step */
+ contextExt->remeshingCount++;
+ _SnacRemesher_DumpInfo( context );
+ }
+}
+
+#if 0
+void _SnacRemesher_Sync( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ Partition_Index i;
+
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ /* Pack (local) shadows required to send to neighbour and send them, for each neighbour */
+ Journal_DPrintf( contextExt->debugSync, "Top nodes shadow syncing starting.\n" );
+ for( i = 0; i < meshExt->neighbourRankCount; i++ ) {
+ Node_ShadowIndex nCount = meshExt->shadowNodeLocalCount[i];
+ Element_ShadowIndex eCount = meshExt->shadowElementLocalCount[i];
+ Node_ShadowIndex node_sI;
+ Element_ShadowIndex element_sI;
+ Coord coordLocal[nCount];
+ Snac_Node* nodeLocal = (Snac_Node*)ExtensionManager_Malloc( mesh->nodeExtensionMgr, nCount );
+
+ Journal_DPrintf( contextExt->debugSync, "Sending node %u coordinates to rank: %u; {", nCount, meshExt->neighbourRank[i] );
+ for( node_sI = 0; node_sI < nCount; node_sI++ ) {
+ coordLocal[node_sI][0] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][0];
+ coordLocal[node_sI][1] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][1];
+ coordLocal[node_sI][2] = mesh->nodeCoord[meshExt->shadowNodeLocalArray[i][node_sI]][2];
+ Journal_DPrintf( contextExt->debugSync, "{ %g, %g, %g }, ", coordLocal[node_sI][0], coordLocal[node_sI][1], coordLocal[node_sI][2] );
+ }
+ Journal_DPrintf( contextExt->debugSync, "}\n" );
+
+ MPI_Send(
+ coordLocal,
+ nCount * 3,
+ MPI_DOUBLE,
+ meshExt->neighbourRank[i],
+ 0,
+ context->communicator );
+
+ Journal_DPrintf( contextExt->debugSync, "Sending node %u to rank: %u\n", nCount, meshExt->neighbourRank[i] );
+ for( node_sI = 0; node_sI < nCount; node_sI++ ) {
+ memcpy(
+ ExtensionManager_At( mesh->nodeExtensionMgr, nodeLocal, node_sI ),
+ Mesh_NodeAt( mesh, meshExt->shadowNodeLocalArray[i][node_sI] ),
+ mesh->nodeExtensionMgr->finalSize );
+ }
+
+ MPI_Send(
+ nodeLocal,
+ nCount * mesh->nodeExtensionMgr->finalSize,
+ MPI_CHAR,
+ meshExt->neighbourRank[i],
+ 1668,
+ context->communicator );
+
+ Journal_DPrintf( contextExt->debugSync, "Sending element %u to rank: %u\n", eCount, meshExt->neighbourRank[i] );
+ for( element_sI = 0; element_sI < eCount; element_sI++ ) {
+ MPI_Send(
+ Mesh_ElementAt( mesh, meshExt->shadowElementLocalArray[i][element_sI] ),
+ mesh->elementExtensionMgr->finalSize,
+ MPI_CHAR,
+ meshExt->neighbourRank[i],
+ 1669+element_sI,
+ context->communicator );
+ }
+
+ ExtensionManager_Free( mesh->nodeExtensionMgr, nodeLocal );
+ }
+
+ /* Receive the associated shadows from each neighbour */
+ for( i = 0; i < meshExt->neighbourRankCount; i++ ) {
+ MPI_Status status;
+ Node_ShadowIndex nCount = meshExt->shadowNodeRemoteCount[i];
+ Element_ShadowIndex eCount = meshExt->shadowElementRemoteCount[i];
+ Node_ShadowIndex node_sI;
+ Element_ShadowIndex element_sI;
+
+ MPI_Recv(
+ meshExt->shadowNodeRemoteCoord[i],
+ nCount * 3,
+ MPI_DOUBLE,
+ meshExt->neighbourRank[i],
+ 0,
+ context->communicator,
+ &status );
+ Journal_DPrintf( contextExt->debugSync, "Received node %u coordinates from rank: %u; {", nCount, meshExt->neighbourRank[i] );
+ for( node_sI = 0; node_sI < nCount; node_sI++ ) {
+ Journal_DPrintf( contextExt->debugSync,
+ "{ %g, %g, %g }, ",
+ meshExt->shadowNodeRemoteCoord[i][node_sI][0],
+ meshExt->shadowNodeRemoteCoord[i][node_sI][1],
+ meshExt->shadowNodeRemoteCoord[i][node_sI][2] );
+ }
+ Journal_DPrintf( contextExt->debugSync, "}\n" );
+
+ MPI_Recv(
+ meshExt->shadowNodeRemote[i],
+ nCount * mesh->nodeExtensionMgr->finalSize,
+ MPI_CHAR,
+ meshExt->neighbourRank[i],
+ 1668,
+ context->communicator,
+ &status );
+ Journal_DPrintf( contextExt->debugSync, "Received node %u from rank: %u\n", nCount, meshExt->neighbourRank[i] );
+
+ for( element_sI = 0; element_sI < eCount; element_sI++ ) {
+ MPI_Recv(
+ ExtensionManager_At( mesh->elementExtensionMgr, meshExt->shadowElementRemote[i], element_sI ),
+ mesh->elementExtensionMgr->finalSize,
+ MPI_CHAR,
+ meshExt->neighbourRank[i],
+ 1669+element_sI,
+ context->communicator,
+ &status );
+ }
+ Journal_DPrintf( contextExt->debugSync, "Received element %u from rank: %u\n", eCount, meshExt->neighbourRank[i] );
+ }
+ Journal_DPrintf( contextExt->debugSync, "Top nodes shadow syncing done.\n" );
+}
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesh.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,65 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Remesh.h 3250 2006-10-23 06:15:18Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Remesh_h__
+#define __SnacRemesher_Remesh_h__
+
+ void _SnacRemesher_Remesh( void* _context, void* data );
+
+/* void _SnacRemesher_Sync( void* _context ); */
+ void _SnacRemesher_NewCoords( void* _context );
+
+ void _SnacRemesher_InterpolateNodes( void* _context );
+ void _SnacRemesher_InterpolateNode( void* context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes );
+
+ void _SnacRemesher_InterpolateElements( void* context );
+ void _SnacRemesher_UpdateElements( void* context );
+ void _SnacRemesher_InterpolateElement(
+ void* _context,
+ Element_LocalIndex dstEltInd,
+ Tetrahedra_Index dstTetInd,
+ Snac_Element* dstEltArray,
+ Element_DomainIndex srcEltInd,
+ Tetrahedra_Index srcTetInd );
+
+
+#endif /* __SnacRemesher_Remesh_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshCoords.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshCoords.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshCoords.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,2131 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Pururav Thoutireddy,
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Pururav Thoutireddy, Staff Scientist, Caltech
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: RemeshCoords.c 3173 2005-11-21 23:47:09Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Remesh.h"
+#include "Register.h"
+
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <float.h>
+
+
+void _SnacRemesher_NewCoords( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+
+ void _SnacRemesher_RemapSurface( void* _context,
+ unsigned nSurfNodes,
+ Node_LocalIndex* surfNodeMap,
+ unsigned nTris,
+ Node_DomainIndex* triNodeMap );
+
+
+ /*
+ ** This rewrite is based on the following assumptions:
+ ** 1. Only the top and bottom internal nodes are free, the rest will be restored to their initial positions.
+ ** 2. ... that's it for now.
+ */
+
+
+ /*
+ ** The left, right, front and back wall nodes will already be stored. Also, the x and z components of the bulk,
+ ** top and bottom nodes will also be pre-calculated. So all that remains is to calculate the y components.
+ */
+
+
+ /*
+ ** Performing a bottom surface remap is only necessary if bottomRestore is false. This is because the newNodeCoords
+ ** array in meshExt will already have the correct bottom values in there by default.
+ */
+
+ if( contextExt->bottomRestore == False ) {
+ _SnacRemesher_RemapSurface( context,
+ meshExt->nBotInternNodes,
+ meshExt->botInternToLocal,
+ meshExt->nBotTriNodes,
+ meshExt->botTriToDomain );
+ }
+
+
+ /*
+ ** Remap the top surface.
+ */
+
+ _SnacRemesher_RemapSurface( context,
+ meshExt->nTopInternNodes,
+ meshExt->topInternToLocal,
+ meshExt->nTopTriNodes,
+ meshExt->topTriToDomain );
+
+
+ /*
+ ** The bulk of the mesh requires some communication, it needs to know both the terminals of
+ ** the y-axis for each y-oriented line.
+ */
+
+ {
+ double* remoteYCoords;
+ SnacSync* sync = meshExt->sync;
+ unsigned yLine_i;
+
+ /* Prepare an array to receive any y coords we need. */
+ if( sync->netSource > 0 ) {
+ remoteYCoords = Memory_Alloc_Array( double, sync->netSource, "SnacRemesher" );
+ }
+ else {
+ remoteYCoords = NULL;
+ }
+
+ /* Send and receive. */
+ SnacSync_SendRecv( sync,
+ &meshExt->newNodeCoords[0][1],
+ remoteYCoords );
+
+ /* Now that we have any required remote y coords, interpolate the local bulk nodes. */
+ for( yLine_i = 0; yLine_i < meshExt->nYLines; yLine_i++ ) {
+ double top;
+ double bot;
+ double h;
+ unsigned ylNode_i;
+
+ /* Find the top coordinate. */
+ if( meshExt->yLineUTerm[yLine_i] < mesh->nodeLocalCount ) {
+ Node_LocalIndex lNodeInd = meshExt->yLineUTerm[yLine_i];
+
+ top = meshExt->newNodeCoords[lNodeInd][1];
+ }
+ else {
+ unsigned remInd = meshExt->yLineUTerm[yLine_i] - mesh->nodeLocalCount;
+
+ top = remoteYCoords[remInd];
+ }
+
+ /* Find the bottom coordinate. */
+ if( meshExt->yLineLTerm[yLine_i] < mesh->nodeLocalCount ) {
+ Node_LocalIndex lNodeInd = meshExt->yLineLTerm[yLine_i];
+
+ bot = meshExt->newNodeCoords[lNodeInd][1];
+ }
+ else {
+ unsigned remInd = meshExt->yLineLTerm[yLine_i] - mesh->nodeLocalCount;
+
+ bot = remoteYCoords[remInd];
+ }
+
+ /* Calculate the interval. */
+ h = (top - bot) / (double)(decomp->nodeGlobal3DCounts[1] - 1);
+
+ /* Interpolate all the local nodes in this y-line. */
+ for( ylNode_i = 0; ylNode_i < meshExt->yLineNYInds[yLine_i]; ylNode_i++ ) {
+ Node_LocalIndex lNodeInd = meshExt->yLineLocalInds[yLine_i][ylNode_i];
+ unsigned yInd = meshExt->yLineYInds[yLine_i][ylNode_i];
+
+ meshExt->newNodeCoords[lNodeInd][1] = bot + h * (double)yInd;
+ }
+ }
+
+ /* Free up resources. */
+ FreeArray( remoteYCoords );
+ }
+}
+
+
+void _SnacRemesher_RemapSurface( void* _context,
+ unsigned nSurfNodes,
+ Node_LocalIndex* surfNodeMap,
+ unsigned nTriNodes,
+ Node_DomainIndex* triNodeMap )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ unsigned surfNode_i;
+
+ Bool _SnacRemesher_PointInTri( Coord pnt, Coord a, Coord b, Coord c );
+ void _SnacRemesher_TriBarycenter( Coord tri[3], Coord pnt, Coord dst );
+
+
+ if( nSurfNodes == 0 ) {
+ return;
+ }
+
+
+ /*
+ ** Loop over the nodes to be mapped (nodeInds) and determine which surface element of the old
+ ** mesh it falls in. Then, interpolate the position there using barycentric coordinates.
+ */
+
+ for( surfNode_i = 0; surfNode_i < nSurfNodes; surfNode_i++ ) {
+ Node_LocalIndex lNodeInd = surfNodeMap[surfNode_i];
+ Coord newCoord;
+ unsigned triNode_i;
+
+ /* Grab the new x and z coords. */
+ newCoord[0] = meshExt->newNodeCoords[lNodeInd][0];
+ newCoord[1] = 0.0;
+ newCoord[2] = meshExt->newNodeCoords[lNodeInd][2];
+
+ /* Find the triangle it's in and interpolate. */
+ for( triNode_i = 0; triNode_i < nTriNodes; triNode_i += 3 ) {
+ Coord tri[3];
+
+ /* Collect the coords of the tri and clear the y component. */
+ Vector_Set( tri[0], mesh->nodeCoord[triNodeMap[triNode_i + 0]] );
+ tri[0][1] = 0.0;
+ Vector_Set( tri[1], mesh->nodeCoord[triNodeMap[triNode_i + 1]] );
+ tri[1][1] = 0.0;
+ Vector_Set( tri[2], mesh->nodeCoord[triNodeMap[triNode_i + 2]] );
+ tri[2][1] = 0.0;
+
+ if( _SnacRemesher_PointInTri( newCoord, tri[0], tri[1], tri[2] ) == True ) {
+ Coord center;
+
+ /* Calculate the barycentric coords of the new point in the triangle, then
+ interpolate. */
+ _SnacRemesher_TriBarycenter( tri, newCoord, center );
+ newCoord[1] = center[0] * mesh->nodeCoord[triNodeMap[triNode_i + 0]][1] +
+ center[1] * mesh->nodeCoord[triNodeMap[triNode_i + 1]][1] +
+ center[2] * mesh->nodeCoord[triNodeMap[triNode_i + 2]][1];
+
+ /* Update the y-axis of the new node coords. */
+ meshExt->newNodeCoords[lNodeInd][1] = newCoord[1];
+
+ break;
+ }
+ }
+
+ /* Note that if the new coord couldn't be projected onto the triangulated surface (the mesh has either
+ contracted too far, drifted too far or there is not enough shadow depth), then the current y coord will
+ be left as is. */
+ }
+}
+
+
+/*
+** Two functions for determining whether a point is inside a triangle. Probably not the fastest
+** way of doing this but it is independant of triangle winding so can be used without a whole lot
+** of extra consideration. Additionally, it may be better to use a 'winding' style solution so that
+** if the surface to be projected onto has folded then we can know if we are projecting onto an
+** unreachable triangle.
+*/
+
+Bool _SnacRemesher_PointInTri( Coord pnt, Coord a, Coord b, Coord c ) {
+ Bool _SnacRemesher_SameSide( Coord pnt, Coord ref, Coord from, Coord to );
+
+ if( _SnacRemesher_SameSide( pnt, a, b, c ) &&
+ _SnacRemesher_SameSide( pnt, b, a, c ) &&
+ _SnacRemesher_SameSide( pnt, c, a, b ) )
+ {
+ return True;
+ }
+ else {
+ return False;
+ }
+}
+
+
+Bool _SnacRemesher_SameSide( Coord pnt, Coord ref, Coord from, Coord to ) {
+ Coord line;
+ Coord cp[2];
+
+ Vector_Sub( line, to, from );
+ Vector_Sub( cp[0], pnt, from );
+ Vector_Sub( cp[1], ref, from );
+ Vector_Cross( cp[0], line, cp[0] );
+ Vector_Cross( cp[1], line, cp[1] );
+
+ return (Vector_Dot( cp[0], cp[1] ) >= -1.0e-16) ? True : False;
+}
+
+
+/*
+** Calculates the barycenter of a triangle with respect to some point.
+*/
+
+void _SnacRemesher_TriBarycenter( Coord tri[3], Coord pnt, Coord dst ) {
+ double a = tri[0][0] - tri[2][0];
+ double b = tri[1][0] - tri[2][0];
+ double c = tri[2][0] - pnt[0];
+ double d = tri[0][1] - tri[2][1];
+ double e = tri[1][1] - tri[2][1];
+ double f = tri[2][1] - pnt[1];
+ double g = tri[0][2] - tri[2][2];
+ double h = tri[1][2] - tri[2][2];
+ double i = tri[2][2] - pnt[2];
+
+ dst[0] = (b * (f + i) - c * (e + h)) / (a * (e + h) - b * (d + g));
+ dst[1] = (a * (f + i) - c * (d + g)) / (b * (d + g) - a * (e + h));
+ dst[2] = 1.0 - dst[0] - dst[1];
+}
+
+
+
+
+
+
+
+#if 0
+/*
+** Removed but not deleted while rewriting the whole damn thing.
+** Luke, 31/06/2005
+*/
+
+
+
+#define DIM 3
+#define NODES_PER_ELEMENT 8
+
+#ifndef MAX
+ #define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+double isLargerThanZero( double, double );
+double isLargerThanZero2( double, double, double );
+double getSignedArea( Coord );
+void xyz2tprCoord( Coord, Coord* );
+void tpr2xyzCoord( Coord, Coord* );
+void xyz2tprVel( Coord, Coord, Coord* );
+void tpr2xyzVel( Coord, Coord, Coord* );
+
+
+
+void _SnacRemesher_NewCoords_Cartesian( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ Node_LocalIndex index;
+ int* ind;
+ Index d;
+ Element_LocalIndex element_lK,element_lI,element_lN;
+ Node_LocalIndex node_lK,node_lI,node_lII,node_lN;
+ Element_LocalIndex nElementX=decomp->elementLocal3DCounts[decomp->rank][0];
+ Element_LocalIndex nElementY=decomp->elementLocal3DCounts[decomp->rank][1];
+ Element_LocalIndex nElementZ=decomp->elementLocal3DCounts[decomp->rank][2];
+ Node_LocalIndex nNodeX=decomp->nodeLocal3DCounts[decomp->rank][0];
+ Node_LocalIndex nNodeY=decomp->nodeLocal3DCounts[decomp->rank][1];
+ Node_LocalIndex nNodeZ=decomp->nodeLocal3DCounts[decomp->rank][2];
+ Element_NodeIndex elementNodeCount;
+ double xc[DIM*NODES_PER_ELEMENT];
+ PartitionIndex rn_I;
+ int count;
+ int en_II[4] = { 3, 2, 6, 7};
+ int nn[2][3] = { {3, 7, 2}, {2, 7, 6} };
+ unsigned int All_passed = 0;
+ double TOL = 0.0f;
+ const int shadowDepth = ( decomp->shadowDepth > 3) ? decomp->shadowDepth : 3;
+ const int numSearchElement = 2*shadowDepth-1;
+ const int numSearchDepth = shadowDepth-1;
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ ind = (int*)malloc( sizeof(int) * nNodeX * nNodeZ );
+ memset( ind, 0, sizeof(int) * nNodeX * nNodeZ );
+
+ while(!All_passed) {
+ /* Calculate the new node coordintates for the top-internal nodes. */
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Tetrahedra_Index tetra_I;
+ Coord initialNodeCoord;
+ Element_LocalIndex searchElement_lI,searchElement_lK;
+ IJK ijk;
+
+ node_lI = node_lII + (nNodeY-1)*nNodeX + node_lK*nNodeX*nNodeY;
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ element_lI = (ijk[0] <= 1)? 0 : (ijk[0]-1);
+ element_lK = (ijk[2] <= 1)? 0 : (ijk[2]-1);
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] ) {
+ continue;
+ }
+
+ initialNodeCoord[0] = meshExt->initialNodeCoord[node_lI][0];
+ initialNodeCoord[1] = 0.0f;
+ initialNodeCoord[2] = meshExt->initialNodeCoord[node_lI][2];
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (element_lK+searchElement_lK-numSearchDepth) < 0 || (element_lK+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (element_lI+searchElement_lI-numSearchDepth) < 0 || (element_lI+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (element_lI+searchElement_lI-numSearchDepth) + (nElementY-1)*nElementX +
+ (element_lK+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] )
+ break;
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = elementNodeTbl[element_lN][en_II[en_N]];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_II[en_N]*DIM+d] );
+ }
+ }
+
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+ /* if the current coord is very close to the initial ones, just copy those initial values rather than bothering to compute determinents and adding error */
+ if( ( meshExt->initialNodeCoord[node_lI][0] >= mesh->nodeCoord[node_lI][0] - TOL*(elembbox[1][0]-elembbox[0][0]) && meshExt->initialNodeCoord[node_lI][0] <= mesh->nodeCoord[node_lI][0] + TOL*(elembbox[1][0]-elembbox[0][0]) ) &&
+ ( meshExt->initialNodeCoord[node_lI][1] >= mesh->nodeCoord[node_lI][1] - TOL*(elembbox[1][1]-elembbox[0][1]) && meshExt->initialNodeCoord[node_lI][1] <= mesh->nodeCoord[node_lI][1] + TOL*(elembbox[1][1]-elembbox[0][1]) ) &&
+ ( meshExt->initialNodeCoord[node_lI][2] >= mesh->nodeCoord[node_lI][2] - TOL*(elembbox[1][2]-elembbox[0][2]) && meshExt->initialNodeCoord[node_lI][2] <= mesh->nodeCoord[node_lI][2] + TOL*(elembbox[1][2]-elembbox[0][2]) ) ) {
+ meshExt->newNodeCoord[node_lI][0] = meshExt->initialNodeCoord[node_lI][0];
+ meshExt->newNodeCoord[node_lI][1] = Mesh_CoordAt( context->mesh, node_lI )[1];
+ meshExt->newNodeCoord[node_lI][2] = meshExt->initialNodeCoord[node_lI][2];
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+ continue;
+ }
+
+ /* if the current coordinate is far enough from the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nn[tetra_I][0]*DIM+d];
+ x2[d] = xc[nn[tetra_I][1]*DIM+d];
+ x3[d] = xc[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+
+ x1[1] = x2[1] = x3[1] = 0.0f;
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+ Vector_Sub( axisA, x2, initialNodeCoord );
+ Vector_Sub( axisB, x3, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoord );
+ Vector_Sub( axisB, x1, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoord );
+ Vector_Sub( axisB, x2, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+ //if( dett <= -1.0e-10 || dett == 0.0)
+ // fprintf(stderr,"me=%d element_lI=%d node_lI=%d TOL=%e det=%e %e %e %e\ninitialCoord=%e %e %e x1=%e %e %e x2=%e %e %e x3=%e %e %e\n",
+ // context->rank,element_lI,node_lI,TOL,det[0],det[1],det[2],dett,initialNodeCoord[0],initialNodeCoord[1],initialNodeCoord[2],
+ // x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2]);
+ //assert( dett > -1.0e-10 && dett != 0.0);
+ //fprintf(stderr,"Top coord: element_lI=%d node_lI=%d tetra_I=%d det's=%e %e %e %e\n",
+ //element_lI,node_lI,tetra_I,dett,det[0],det[1],det[2]);
+ //fprintf(stderr,"tetra_I=%d dett=%e det0=%e det1=%e det2=%e\n",tetra_I,dett,det[0],det[1],det[2]);
+
+
+ if( dett < 0 ) {
+ //assert(0);
+ continue;
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+ //fprintf(stderr,"dett=%e det0=%e det1=%e det2=%e shape=%e %e %e\n",dett,det[0],det[1],det[2],shape[0],shape[1],shape[2]);
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ //meshExt->newNodeCoord[node_lI][1] -= TOL*fabs(meshExt->newNodeCoord[node_lI][1]);
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+
+ break;
+ }
+#if 0
+ if(node_lII==0 && node_lK==0)
+ fprintf(stderr,"Found? %d timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoord[0],initialNodeCoord[1],initialNodeCoord[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+ IJK eijkN;
+
+ /* skip irrelevant elements or exit the loop once the interpolation is done (ind == 1). */
+ RegularMeshUtils_Element_1DTo3D( decomp, gElement_N, &eijkN[0], &eijkN[1], &eijkN[2] );
+ if(eijkN[1] != decomp->elementGlobal3DCounts[1]-1)
+ continue;
+ if(ind[ijk[0]+ijk[2]*nNodeX] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < 8; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ Index node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ unsigned int found = 0;
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] =
+ context->mesh->nodeGlobalCount +
+ node_sI;
+ found = 1;
+ break;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ elementNodeCount = (unsigned)NODES_PER_ELEMENT; /* Assume all shadow elements have 8 nodes per el */
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_sN = %d", element_sN );
+ assert( 0 );
+ }
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = shadowElementNodesN[en_II[en_N]];
+ if( node_lN < context->mesh->nodeDomainCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_II[en_N]*DIM+d] );
+ }
+ }
+
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nn[tetra_I][0]*DIM+d];
+ x2[d] = xc[nn[tetra_I][1]*DIM+d];
+ x3[d] = xc[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+
+ Vector_Sub( axisA, x2, initialNodeCoord );
+ Vector_Sub( axisB, x3, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoord );
+ Vector_Sub( axisB, x1, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoord );
+ Vector_Sub( axisB, x2, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+
+ if( dett < 0 ) {
+ printf( "Determinant evaluation is wrong node=%d\t xt[0]=%g \t xt[1]=%g \t xt[t]=%g\n",
+ node_lI,
+ initialNodeCoord[0],
+ initialNodeCoord[1],
+ initialNodeCoord[2]);
+ continue;
+ //assert(0);
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+
+ break;
+ }
+#if 0
+ if(context->rank==1 && node_lI==44)
+ fprintf(stderr,"Shadow Found? %d ind=%d timeStep=%d me=%d gElment_N=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,ind[ijk[0]+ijk[2]*nNodeX],context->timeStep,context->rank,gElement_N,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoord[0],initialNodeCoord[1],initialNodeCoord[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ node_lI=node_lII+(nNodeY-1)*nNodeX+node_lK*nNodeX*nNodeY;
+ if( ind[node_lII+node_lK*nNodeX] == 0 ) {
+ count++;
+ All_passed = 0;
+ fprintf(stderr,"me=%d TOP failed node_lI=%d TOL=%e\n",context->rank,node_lI,TOL);
+ }
+ }
+ if(TOL==0.0)TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s, timeStep=%d rank=%d Increased tolerance for Top: %e count=%d\n", __func__, context->timeStep, context->rank, TOL,count );
+ Journal_DPrintf( context->debug, " In: %s, rank=%d Increased tolerance for Top: %e count=%d\n", __func__, context->rank, TOL,count );
+ }
+ /* Calculate the new node coordintates for the bottom-internal nodes. */
+ if(contextExt->bottomRestore) {
+ for( index = 0; index < meshExt->bottomInternalCount; index++ ) {
+ node_lI = meshExt->bottomInternalArray[index];
+ meshExt->newNodeCoord[node_lI][0] = meshExt->initialNodeCoord[node_lI][0];
+ meshExt->newNodeCoord[node_lI][1] = meshExt->initialNodeCoord[node_lI][1];
+ meshExt->newNodeCoord[node_lI][2] = meshExt->initialNodeCoord[node_lI][2];
+ }
+ }
+ else {
+ en_II[0] = 0; en_II[1] = 1; en_II[2] = 5; en_II[3] = 4;
+ nn[0][0] = 0; nn[0][1] = 4; nn[0][2] = 1;
+ nn[1][0] = 1; nn[1][1] = 4; nn[1][2] = 5;
+ count = 0;
+ memset( ind, 0, sizeof( int ) * nNodeX * nNodeZ );
+
+ All_passed = 0;
+ TOL= 0.0f;
+ while(!All_passed) {
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Coord initialNodeCoord;
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Tetrahedra_Index tetra_I;
+ Element_LocalIndex searchElement_lI,searchElement_lK;
+ IJK ijk;
+
+ node_lI = node_lII + node_lK*nNodeX*nNodeY;
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ element_lI = (ijk[0] <= 1)? 0 : (ijk[0]-1);
+ element_lK = (ijk[2] <= 1)? 0 : (ijk[2]-1);
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] ) {
+ continue;
+ }
+
+ initialNodeCoord[0] = meshExt->initialNodeCoord[node_lI][0];
+ initialNodeCoord[1] = 0.0f;
+ initialNodeCoord[2] = meshExt->initialNodeCoord[node_lI][2];
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (element_lK+searchElement_lK-numSearchDepth) < 0 || (element_lK+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (element_lI+searchElement_lI-numSearchDepth) < 0 || (element_lI+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (element_lI+searchElement_lI-numSearchDepth) + (element_lK+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] )
+ break;
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = elementNodeTbl[element_lN][en_II[en_N]];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_II[en_N]*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nn[tetra_I][0]*DIM+d];
+ x2[d] = xc[nn[tetra_I][1]*DIM+d];
+ x3[d] = xc[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+
+ x1[1] = x2[1] = x3[1] = 0.0f;
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+ Vector_Sub( axisA, x2, initialNodeCoord );
+ Vector_Sub( axisB, x3, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoord );
+ Vector_Sub( axisB, x1, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoord );
+ Vector_Sub( axisB, x2, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ assert( dett > -1.0e-10 && dett != 0.0);
+ dett = det[0] + det[1] + det[2];
+
+ if( dett < 0 ) {
+ continue;
+ //assert(0);
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+
+ break;
+ }
+#if 0
+ fprintf(stderr,"Found? %d timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoord[0],initialNodeCoord[1],initialNodeCoord[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+ IJK eijkN;
+
+ /* skip irrelevant elements or exit the loop once the interpolation is done (ind == 1). */
+ RegularMeshUtils_Element_1DTo3D( decomp, gElement_N, &eijkN[0], &eijkN[1], &eijkN[2] );
+ if(eijkN[1] != 0)
+ continue;
+ if(ind[ijk[0]+ijk[2]*nNodeX] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < 8; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ Node_LocalIndex node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ unsigned int found = 0;
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] =
+ context->mesh->nodeGlobalCount +
+ node_sI;
+ found = 1;
+ break;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ elementNodeCount = (unsigned)NODES_PER_ELEMENT; /* Assume all shadow elements have 8 nodes per el */
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_sN = %d", element_sN );
+ assert( 0 );
+ }
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = shadowElementNodesN[en_II[en_N]];
+ if( node_lN < context->mesh->nodeDomainCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_II[en_N]*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+
+ /* if the current coord is very close to the initial ones, just copy those initial values rather than bothering to compute determinents and adding error */
+ if( ( initialNodeCoord[0] >= Mesh_CoordAt( context->mesh, node_lI )[0] - TOL*(elembbox[1][0]-elembbox[0][0]) && initialNodeCoord[0] <= Mesh_CoordAt( context->mesh, node_lI )[0] + TOL*(elembbox[1][0]-elembbox[0][0]) ) &&
+ ( initialNodeCoord[1] >= Mesh_CoordAt( context->mesh, node_lI )[1] - TOL*(elembbox[1][1]-elembbox[0][1]) && initialNodeCoord[1] <= Mesh_CoordAt( context->mesh, node_lI )[1] + TOL*(elembbox[1][1]-elembbox[0][1]) ) &&
+ ( initialNodeCoord[2] >= Mesh_CoordAt( context->mesh, node_lI )[2] - TOL*(elembbox[1][2]-elembbox[0][2]) && initialNodeCoord[2] <= Mesh_CoordAt( context->mesh, node_lI )[2] + TOL*(elembbox[1][2]-elembbox[0][2]) ) ) {
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = Mesh_CoordAt( context->mesh, node_lI )[1];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nn[tetra_I][0]*DIM+d];
+ x2[d] = xc[nn[tetra_I][1]*DIM+d];
+ x3[d] = xc[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+
+ Vector_Sub( axisA, x2, initialNodeCoord );
+ Vector_Sub( axisB, x3, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoord );
+ Vector_Sub( axisB, x1, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoord );
+ Vector_Sub( axisB, x2, initialNodeCoord );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+
+ if( dett < 0 ) {
+ continue;
+ }
+
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+ count++;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ node_lI=node_lII+(nNodeY-1)*nNodeX+node_lK*nNodeX*nNodeY;
+ if( ind[node_lII+node_lK*nNodeX] == 0 ) {
+ All_passed = 0;
+ count++;
+ fprintf(stderr,"me=%d BOT failed node_lI=%d TOL=%e\n",context->rank,node_lI,TOL);
+ }
+ }
+ if(TOL==0.0)TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s, timeStep=%d rank=%d Increased tolerance for Bottom: %e count=%d\n", __func__, context->timeStep, context->rank, TOL,count );
+ Journal_DPrintf( context->debug, " In: %s, rank=%d Increased tolerance for Bottom: %e count=%d\n", __func__, context->rank, TOL, count );
+ }
+ }
+ free( ind );
+
+ /* Calculate the new node coordintates for the wall nodes. */
+ if( meshExt->meshType == -1 ) {
+ assert( 0 );
+ }
+ else { /* SnacRemesher_Cartesian */
+ for( index = 0; index < meshExt->wallCount; index++ ) {
+ Node_LocalIndex node_lI;
+ IJK ijk;
+ Node_LocalIndex nodeTop_lI, nodeBottom_lI;
+ const Index topI = decomp->nodeLocal3DCounts[decomp->rank][1];
+
+ node_lI = meshExt->wallArray[index];
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+
+ /* The wall node positions revert to the initial position */
+ meshExt->newNodeCoord[node_lI][0] = meshExt->initialNodeCoord[node_lI][0];
+ meshExt->newNodeCoord[node_lI][2] = meshExt->initialNodeCoord[node_lI][2];
+ nodeBottom_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], 0, ijk[2] );
+ nodeTop_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], topI - 1, ijk[2] );
+ meshExt->newNodeCoord[node_lI][1] =
+ meshExt->newNodeCoord[nodeBottom_lI][1] +
+ ( meshExt->newNodeCoord[nodeTop_lI][1] - meshExt->newNodeCoord[nodeBottom_lI][1] ) /
+ (topI - 1 ) *
+ ijk[1];
+ }
+ }
+
+ for( index = 0; index < meshExt->internalCount; index++ ) {
+ Node_LocalIndex node_lI;
+ IJK ijk;
+ Node_LocalIndex nodeBottom_lI;
+ Node_LocalIndex nodeTop_lI;
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ const Index topI = decomp->nodeLocal3DCounts[decomp->rank][1];
+
+ /* TODO... parallel version! */
+ node_lI = meshExt->internalArray[index];
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ /* TODO... Local? where's the global equivalent? */
+ nodeBottom_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], 0, ijk[2] );
+ nodeTop_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], topI - 1, ijk[2] );
+
+ meshExt->newNodeCoord[node_lI][0] = meshExt->initialNodeCoord[node_lI][0];
+ meshExt->newNodeCoord[node_lI][1] =
+ meshExt->newNodeCoord[nodeBottom_lI][1] +
+ ( meshExt->newNodeCoord[nodeTop_lI][1] - meshExt->newNodeCoord[nodeBottom_lI][1] ) /
+ (topI - 1 ) *
+ ijk[1];
+ meshExt->newNodeCoord[node_lI][2] = meshExt->initialNodeCoord[node_lI][2];
+ }
+}
+
+void _SnacRemesher_NewCoords_Spherical( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ Node_LocalIndex index;
+ Node_LocalIndex node_lI,node_lII,node_lK,node_lN;
+ int* ind;
+ Index d;
+ Element_LocalIndex element_lK,element_lJ,element_lI,element_lN;
+ Element_LocalIndex nElementX=decomp->elementLocal3DCounts[decomp->rank][0];
+ Element_LocalIndex nElementY=decomp->elementLocal3DCounts[decomp->rank][1];
+ Element_LocalIndex nElementZ=decomp->elementLocal3DCounts[decomp->rank][2];
+ Node_LocalIndex nNodeX=decomp->nodeLocal3DCounts[decomp->rank][0];
+ Node_LocalIndex nNodeY=decomp->nodeLocal3DCounts[decomp->rank][1];
+ Node_LocalIndex nNodeZ=decomp->nodeLocal3DCounts[decomp->rank][2];
+ Element_NodeIndex elementNodeCount;
+ double xc[DIM*NODES_PER_ELEMENT];
+ double xcs[DIM*NODES_PER_ELEMENT];
+ PartitionIndex rn_I;
+ int count;
+ int en_II[4] = { 3, 2, 6, 7};
+ int nn[2][3] = { {3, 7, 2}, {2, 7, 6} };
+ unsigned int All_passed = 0;
+ double TOL = 0.0f;
+ const int shadowDepth = ( decomp->shadowDepth > 3) ? decomp->shadowDepth : 3;
+ const int numSearchElement = 2*shadowDepth-1;
+ const int numSearchDepth = shadowDepth-1;
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ ind = (int*)malloc( sizeof( int ) * nNodeX * nNodeZ );
+ memset( ind, 0, sizeof( int ) * nNodeX * nNodeZ );
+
+ while(!All_passed) {
+ /* Calculate the new node coordintates for the top-internal nodes. */
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Coord temp1,temp2;
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Tetrahedra_Index tetra_I;
+ Coord initialNodeCoord;
+ Coord initialNodeCoordS;
+ Element_LocalIndex searchElement_lI,searchElement_lK;
+ IJK ijk;
+
+ /* Ensure we haven't already done this node */
+ node_lI = node_lII + (nNodeY-1)*nNodeX + node_lK*nNodeX*nNodeY;
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ element_lI = (ijk[0] <= 1)? 0 : (ijk[0]-1);
+ element_lK = (ijk[2] <= 1)? 0 : (ijk[2]-1);
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] ) {
+ continue;
+ }
+
+ initialNodeCoord[0] = meshExt->initialNodeCoord[node_lI][0];
+ initialNodeCoord[1] = meshExt->initialNodeCoord[node_lI][1];
+ initialNodeCoord[2] = meshExt->initialNodeCoord[node_lI][2];
+ xyz2tprCoord( initialNodeCoord, &initialNodeCoordS );
+ initialNodeCoordS[1] = 0.0f;
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (element_lK+searchElement_lK-numSearchDepth) < 0 || (element_lK+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (element_lI+searchElement_lI-numSearchDepth) < 0 || (element_lI+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (element_lI+searchElement_lI-numSearchDepth) + (nElementY-1)*nElementX +
+ (element_lK+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] )
+ break;
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = elementNodeTbl[element_lN][en_II[en_N]];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_II[en_N]*DIM+0];
+ temp1[1] = xc[en_II[en_N]*DIM+1];
+ temp1[2] = xc[en_II[en_N]*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_II[en_N]*DIM+0] = temp2[0];
+ xcs[en_II[en_N]*DIM+1] = temp2[1];
+ xcs[en_II[en_N]*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_II[en_N]*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+
+ /* if the current coordinate is far enough from the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nn[tetra_I][0]*DIM+d];
+ x2[d] = xcs[nn[tetra_I][1]*DIM+d];
+ x3[d] = xcs[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+ Vector_Sub( axisA, x2, initialNodeCoordS );
+ Vector_Sub( axisB, x3, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoordS );
+ Vector_Sub( axisB, x1, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoordS );
+ Vector_Sub( axisB, x2, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+
+ if( dett < 0 ) {
+ continue;
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ x1[0] = initialNodeCoordS[0];
+ x1[1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ x1[2] = initialNodeCoordS[2];
+ tpr2xyzCoord( x1,&meshExt->newNodeCoord[node_lI] );
+
+ break;
+ }
+#if 0
+ if(context->rank==0 && node_lI==0 && TOL <= 1.0e-7)
+ fprintf(stderr,"Found? %d TOL=%e timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e min=%e max=%e result=%e\n\n",
+ found,TOL,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoordS[0],initialNodeCoordS[1],initialNodeCoordS[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett,-1.0*fabs(dett)*TOL,fabs(dett)*TOL,
+ isLargerThanZero2(det[0],dett,TOL));
+#endif
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+ IJK eijkN;
+
+ /* skip irrelevant elements or exit the loop once the interpolation is done (ind == 1). */
+ RegularMeshUtils_Element_1DTo3D( decomp, gElement_N, &eijkN[0], &eijkN[1], &eijkN[2] );
+ if(eijkN[1] != decomp->elementGlobal3DCounts[1]-1)
+ continue;
+ if(ind[ijk[0]+ijk[2]*nNodeX] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < 8; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ unsigned int found = 0;
+ node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] =
+ context->mesh->nodeGlobalCount +
+ node_sI;
+ found = 1;
+ break;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ elementNodeCount = (unsigned)NODES_PER_ELEMENT; /* Assume all shadow elements have 8 nodes per el */
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_sN = %d", element_sN );
+ assert( 0 );
+ }
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = shadowElementNodesN[en_II[en_N]];
+ if( node_lN < context->mesh->nodeDomainCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_II[en_N]*DIM+0];
+ temp1[1] = xc[en_II[en_N]*DIM+1];
+ temp1[2] = xc[en_II[en_N]*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_II[en_N]*DIM+0] = temp2[0];
+ xcs[en_II[en_N]*DIM+1] = temp2[1];
+ xcs[en_II[en_N]*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_II[en_N]*DIM+d] );
+ }
+ }
+
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ continue;
+ }
+
+ /* if the current coord is very close to the initial ones, just copy those initial values rather than bothering to compute determinents and adding error */
+ if( ( initialNodeCoord[0] >= Mesh_CoordAt( context->mesh, node_lI )[0] - TOL*(elembbox[1][0]-elembbox[0][0]) && initialNodeCoord[0] <= Mesh_CoordAt( context->mesh, node_lI )[0] + TOL*(elembbox[1][0]-elembbox[0][0]) ) &&
+ ( initialNodeCoord[1] >= Mesh_CoordAt( context->mesh, node_lI )[1] - TOL*(elembbox[1][1]-elembbox[0][1]) && initialNodeCoord[1] <= Mesh_CoordAt( context->mesh, node_lI )[1] + TOL*(elembbox[1][1]-elembbox[0][1]) ) &&
+ ( initialNodeCoord[2] >= Mesh_CoordAt( context->mesh, node_lI )[2] - TOL*(elembbox[1][2]-elembbox[0][2]) && initialNodeCoord[2] <= Mesh_CoordAt( context->mesh, node_lI )[2] + TOL*(elembbox[1][2]-elembbox[0][2]) ) ) {
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = Mesh_CoordAt( context->mesh, node_lI )[1];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nn[tetra_I][0]*DIM+d];
+ x2[d] = xcs[nn[tetra_I][1]*DIM+d];
+ x3[d] = xcs[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+
+ Vector_Sub( axisA, x2, initialNodeCoordS );
+ Vector_Sub( axisB, x3, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoordS );
+ Vector_Sub( axisB, x1, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoordS );
+ Vector_Sub( axisB, x2, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+ assert( dett > -1.0e-10 && dett != 0.0);
+
+ if( dett < 0 ) {
+ continue;
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ x1[0] = initialNodeCoordS[0];
+ x1[1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ x1[2] = initialNodeCoordS[2];
+ tpr2xyzCoord( x1, &meshExt->newNodeCoord[node_lI] );
+ }
+#if 0
+ if(context->rank==2 && node_lI==594)
+ fprintf(stderr,"Shadow Found? %d TOL=%e timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,TOL,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoordS[0],initialNodeCoordS[1],initialNodeCoordS[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ node_lI=node_lII+(nNodeY-1)*nNodeX+node_lK*nNodeX*nNodeY;
+ if( ind[node_lII+node_lK*nNodeX] == 0 ) {
+ count++;
+ All_passed = 0;
+ }
+ }
+ if(TOL==0.0) TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_DPrintf( context->debug," In: %s, rank=%d Increased tolerance for Top: %e count=%d\n", __func__, context->rank, TOL,count );
+ Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s, timeStep=%d rank=%d Increased tolerance for Top: %e count=%d\n", __func__, context->timeStep, context->rank, TOL,count );
+ }
+
+ /* Calculate the new node coordintates for the bottom-internal nodes. */
+ if(contextExt->bottomRestore) {
+ for( index = 0; index < meshExt->bottomInternalCount; index++ ) {
+ node_lI = meshExt->bottomInternalArray[index];
+ meshExt->newNodeCoord[node_lI][0] = meshExt->initialNodeCoord[node_lI][0];
+ meshExt->newNodeCoord[node_lI][1] = meshExt->initialNodeCoord[node_lI][1];
+ meshExt->newNodeCoord[node_lI][2] = meshExt->initialNodeCoord[node_lI][2];
+ }
+ }
+ else {
+ en_II[0] = 0; en_II[1] = 1; en_II[2] = 5; en_II[3] = 4;
+ nn[0][0] = 0; nn[0][1] = 4; nn[0][2] = 1;
+ nn[1][0] = 1; nn[1][1] = 4; nn[1][2] = 5;
+ memset( ind, 0, sizeof( int ) * nNodeX * nNodeZ );
+
+ All_passed = 0;
+ TOL= 0.0f;
+ while(!All_passed) {
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Coord temp1,temp2;
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Element_LocalIndex searchElement_lI,searchElement_lK;
+ Tetrahedra_Index tetra_I;
+ Coord initialNodeCoord;
+ Coord initialNodeCoordS;
+ IJK ijk;
+
+ node_lI = node_lII + node_lK*nNodeX*nNodeY;
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ element_lI = (ijk[0] <= 1)? 0 : (ijk[0]-1);
+ element_lK = (ijk[2] <= 1)? 0 : (ijk[2]-1);
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] ) {
+ continue;
+ }
+
+ initialNodeCoord[0] = meshExt->initialNodeCoord[node_lI][0];
+ initialNodeCoord[1] = meshExt->initialNodeCoord[node_lI][1];
+ initialNodeCoord[2] = meshExt->initialNodeCoord[node_lI][2];
+ xyz2tprCoord( initialNodeCoord, &initialNodeCoordS );
+ initialNodeCoordS[1] = 0.0f;
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (element_lK+searchElement_lK-numSearchDepth) < 0 || (element_lK+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (element_lI+searchElement_lI-numSearchDepth) < 0 || (element_lI+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (element_lI+searchElement_lI-numSearchDepth) + (element_lK+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ if( ind[ijk[0]+ijk[2]*nNodeX] )
+ break;
+
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ node_lN = elementNodeTbl[element_lN][en_II[en_N]];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_II[en_N]*DIM+0];
+ temp1[1] = xc[en_II[en_N]*DIM+1];
+ temp1[2] = xc[en_II[en_N]*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_II[en_N]*DIM+0] = temp2[0];
+ xcs[en_II[en_N]*DIM+1] = temp2[1];
+ xcs[en_II[en_N]*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_II[en_N]*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nn[tetra_I][0]*DIM+d];
+ x2[d] = xcs[nn[tetra_I][1]*DIM+d];
+ x3[d] = xcs[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+ Vector_Sub( axisA, x2, initialNodeCoordS );
+ Vector_Sub( axisB, x3, initialNodeCoordS );
+
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoordS );
+ Vector_Sub( axisB, x1, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoordS );
+ Vector_Sub( axisB, x2, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+
+ if( dett <= 0 ) {
+ printf( "Determinant evaluation is wrong node=%d\t xt[0]=%g \t xt[1]=%g \t xt[t]=%g\n",
+ en_N,
+ initialNodeCoordS[0],
+ initialNodeCoordS[1],
+ initialNodeCoordS[2]);
+ //assert(0);
+ continue;
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ x1[0] = initialNodeCoordS[0];
+ x1[1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ x1[2] = initialNodeCoordS[2];
+ tpr2xyzCoord( x1, &meshExt->newNodeCoord[node_lI] );
+
+ break;
+ }
+#if 0
+ if(context->rank==0 && node_lI==0)
+ fprintf(stderr,"Found? %d timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoordS[0],initialNodeCoordS[1],initialNodeCoordS[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+ IJK eijkN;
+
+ /* skip irrelevant elements or exit the loop once the interpolation is done (ind == 1). */
+ RegularMeshUtils_Element_1DTo3D( decomp, gElement_N, &eijkN[0], &eijkN[1], &eijkN[2] );
+ if(eijkN[1] != 0)
+ continue;
+ if(ind[ijk[0]+ijk[2]*nNodeX] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < 8; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ unsigned int found = 0;
+ node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] =
+ context->mesh->nodeGlobalCount +
+ node_sI;
+ found = 1;
+ break;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ elementNodeCount = (unsigned)NODES_PER_ELEMENT; /* Assume all shadow elements have 8 nodes per el */
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_sN = %d", element_sN );
+ assert( 0 );
+ }
+
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < 4; en_N++) {
+ node_lN = shadowElementNodesN[en_II[en_N]];
+ if( node_lN < context->mesh->nodeDomainCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_II[en_N]*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_II[en_N]*DIM+0];
+ temp1[1] = xc[en_II[en_N]*DIM+1];
+ temp1[2] = xc[en_II[en_N]*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_II[en_N]*DIM+0] = temp2[0];
+ xcs[en_II[en_N]*DIM+1] = temp2[1];
+ xcs[en_II[en_N]*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < 4; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_II[en_N]*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_II[en_N]*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( initialNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ initialNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ initialNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ continue;
+ }
+
+ /* if the current coord is very close to the initial ones, just copy those initial values rather than bothering to compute determinents and adding error */
+ if( ( initialNodeCoord[0] >= Mesh_CoordAt( context->mesh, node_lI )[0] - TOL*(elembbox[1][0]-elembbox[0][0]) && initialNodeCoord[0] <= Mesh_CoordAt( context->mesh, node_lI )[0] + TOL*(elembbox[1][0]-elembbox[0][0]) ) &&
+ ( initialNodeCoord[1] >= Mesh_CoordAt( context->mesh, node_lI )[1] - TOL*(elembbox[1][1]-elembbox[0][1]) && initialNodeCoord[1] <= Mesh_CoordAt( context->mesh, node_lI )[1] + TOL*(elembbox[1][1]-elembbox[0][1]) ) &&
+ ( initialNodeCoord[2] >= Mesh_CoordAt( context->mesh, node_lI )[2] - TOL*(elembbox[1][2]-elembbox[0][2]) && initialNodeCoord[2] <= Mesh_CoordAt( context->mesh, node_lI )[2] + TOL*(elembbox[1][2]-elembbox[0][2]) ) ) {
+ meshExt->newNodeCoord[node_lI][0] = initialNodeCoord[0];
+ meshExt->newNodeCoord[node_lI][1] = Mesh_CoordAt( context->mesh, node_lI )[1];
+ meshExt->newNodeCoord[node_lI][2] = initialNodeCoord[2];
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+ continue;
+ }
+
+ /* if the current coordinate is far enough fromt the initial position,
+ try to interpolate surface topo. */
+ /* loop over 2 sub triangles in a rectangular element, work out the triangle it is in, and then interpolate */
+ for( tetra_I = 0; tetra_I < 2; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double y1,y2,y3;
+ double dett;
+ double det[3];
+ Coord axisA,axisB,axisC;
+ unsigned int found=0;
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nn[tetra_I][0]*DIM+d];
+ x2[d] = xcs[nn[tetra_I][1]*DIM+d];
+ x3[d] = xcs[nn[tetra_I][2]*DIM+d];
+ }
+ y1 = x1[1];
+ y2 = x2[1];
+ y3 = x3[1];
+ x1[1] = x2[1] = x3[1] = 0.0f;
+
+ Vector_Sub( axisA, x2, x1 );
+ Vector_Sub( axisB, x3, x1 );
+ Vector_Cross( axisC, axisA, axisB );
+ dett = 0.5*getSignedArea( axisC );
+ dett = isLargerThanZero2(dett, dett, TOL);
+
+ Vector_Sub( axisA, x2, initialNodeCoordS );
+ Vector_Sub( axisB, x3, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[0] = 0.5*getSignedArea( axisC );
+ det[0] = isLargerThanZero2(det[0], dett, TOL);
+ Vector_Sub( axisA, x3, initialNodeCoordS );
+ Vector_Sub( axisB, x1, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[1] = 0.5*getSignedArea( axisC );
+ det[1] = isLargerThanZero2(det[1], dett, TOL);
+ Vector_Sub( axisA, x1, initialNodeCoordS );
+ Vector_Sub( axisB, x2, initialNodeCoordS );
+ Vector_Cross( axisC, axisA, axisB );
+ det[2] = 0.5*getSignedArea( axisC );
+ det[2] = isLargerThanZero2(det[2], dett, TOL);
+ dett = det[0] + det[1] + det[2];
+
+ assert( dett > 0.0);
+ if( dett <= 0 ) {
+ continue;
+ }
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[3];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ ind[ijk[0]+ijk[2]*nNodeX] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 3; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ x1[0] = initialNodeCoordS[0];
+ x1[1] = y1*shape[0] + y2*shape[1] + y3*shape[2];
+ x1[2] = initialNodeCoordS[2];
+ tpr2xyzCoord( x1, &meshExt->newNodeCoord[node_lI] );
+ }
+#if 0
+ if(context->rank==0 && node_lI==0)
+ fprintf(stderr,"Shadow Found? %d timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e)(%e %e %e) initialX=%e %e %e\nbbox=(%e %e) (%e %e)\ndett=%e %e %e %e\n\n",
+ found,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],
+ initialNodeCoordS[0],initialNodeCoordS[1],initialNodeCoordS[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],dett);
+#endif
+ }
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lK = 0; node_lK < nNodeZ; node_lK++ )
+ for( node_lII = 0; node_lII < nNodeX; node_lII++ ) {
+ node_lI=node_lII+(nNodeY-1)*nNodeX+node_lK*nNodeX*nNodeY;
+ if( ind[node_lII+node_lK*nNodeX] == 0 ) {
+ All_passed = 0;
+ count++;
+ //fprintf(stderr,"me=%d failed Bottom nodes=%d\n",context->rank,node_lI);
+ }
+ }
+ if(TOL==0.0)TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_DPrintf( context->debug," In: %s, rank=%d Increased tolerance for Bottom: %e count=%d\n", __func__, context->rank, TOL, count );
+ Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s, timeStep=%d rank=%d Increased tolerance for Bottom: %e count=%d\n", __func__, context->timeStep, context->rank, TOL,count );
+ }
+ }
+ free( ind );
+
+ /* Calculate the new node coordintates for the wall nodes. */
+ if( meshExt->meshType == -1 ) {
+ assert( 0 );
+ }
+ else {
+ for( index = 0; index < meshExt->wallCount; index++ ) {
+ Node_LocalIndex node_lI;
+ IJK ijk;
+ Node_LocalIndex nodeTop_lI, nodeBottom_lI;
+ const Index topI = decomp->nodeLocal3DCounts[decomp->rank][1];
+ Coord temp,tempTop,tempBottom;
+ node_lI = meshExt->wallArray[index];
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+
+ /* The wall node positions revert to the initial position */
+ nodeBottom_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], 0, ijk[2] );
+ nodeTop_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], topI - 1, ijk[2] );
+
+ xyz2tprCoord( meshExt->initialNodeCoord[node_lI], &temp );
+ xyz2tprCoord( meshExt->newNodeCoord[nodeTop_lI], &tempTop );
+ xyz2tprCoord( meshExt->newNodeCoord[nodeBottom_lI], &tempBottom );
+
+ temp[1] = tempBottom[1] + (tempTop[1] - tempBottom[1])/(topI - 1 )*ijk[1];
+
+ tpr2xyzCoord( temp, &meshExt->newNodeCoord[node_lI] );
+ }
+ }
+
+ /* Calculate the new node coordintates for the internal nodes. */
+ for( index = 0; index < meshExt->internalCount; index++ ) {
+ Node_LocalIndex node_lI;
+ IJK ijk;
+ Node_LocalIndex nodeBottom_lI, nodeLeft_lI, nodeFront_lI;
+ Node_LocalIndex nodeTop_lI, nodeRight_lI, nodeBack_lI;
+ const Index topI = decomp->nodeLocal3DCounts[decomp->rank][1];
+ const Index rightI = decomp->nodeLocal3DCounts[decomp->rank][0];
+ const Index frontI = decomp->nodeLocal3DCounts[decomp->rank][2];
+ Coord temp,tempTop,tempBottom,tempLeft,tempRight,tempBack,tempFront;
+
+ /* TODO... parallel version! */
+ node_lI = meshExt->internalArray[index];
+ RegularMeshUtils_Node_Local1DTo3D( decomp, node_lI, &ijk[0], &ijk[1], &ijk[2] );
+ /* TODO... Local? where's the global equivalent? */
+ nodeBottom_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], 0, ijk[2] );
+ nodeTop_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], topI - 1, ijk[2] );
+ nodeLeft_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, 0, ijk[1], ijk[2] );
+ nodeRight_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, rightI - 1, ijk[1], ijk[2] );
+ nodeBack_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], ijk[1], 0 );
+ nodeFront_lI = RegularMeshUtils_Node_Local3DTo1D( decomp, ijk[0], ijk[1], frontI - 1 );
+ xyz2tprCoord( meshExt->newNodeCoord[nodeTop_lI], &tempTop );
+ xyz2tprCoord( meshExt->newNodeCoord[nodeBottom_lI], &tempBottom );
+ xyz2tprCoord( meshExt->initialNodeCoord[nodeLeft_lI], &tempLeft );
+ xyz2tprCoord( meshExt->initialNodeCoord[nodeRight_lI], &tempRight );
+ xyz2tprCoord( meshExt->initialNodeCoord[nodeBack_lI], &tempBack );
+ xyz2tprCoord( meshExt->initialNodeCoord[nodeFront_lI], &tempFront );
+
+ temp[0] = tempLeft[0] + (tempRight[0] - tempLeft[0])/(rightI - 1 )*ijk[0];
+ temp[1] = tempBottom[1] + (tempTop[1] - tempBottom[1])/(topI - 1 )*ijk[1];
+ temp[2] = tempBack[2] + (tempFront[2] - tempBack[2])/(frontI - 1 )*ijk[2];
+
+ tpr2xyzCoord( temp, &meshExt->newNodeCoord[node_lI] );
+ }
+}
+
+double isLargerThanZero(double a, double TOL)
+{
+ if(a>=-1.0*TOL && a<=TOL)
+ return 0.0f;
+ else
+ return a;
+}
+double isLargerThanZero2(double a, double refval, double TOL)
+{
+ if(a>=-1.0*fabs(refval)*TOL && a<=fabs(refval)*TOL)
+ return 0.0f;
+ else
+ return a;
+}
+double getSignedArea( Coord a )
+{
+ if(a[1] >= 0.0)
+ return Vector_Mag(a);
+ else
+ return -1.0f*Vector_Mag(a);
+}
+void xyz2tprCoord( Coord x, Coord* dest )
+{
+ (*dest)[0] = atan2(x[1],x[0]);
+ (*dest)[1] = sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
+ (*dest)[2] = acos(x[2]/(*dest)[1]);
+}
+void tpr2xyzCoord( Coord s, Coord* dest )
+{
+ (*dest)[0] = s[1]*sin(s[2])*cos(s[0]);
+ (*dest)[1] = s[1]*sin(s[2])*sin(s[0]);
+ (*dest)[2] = s[1]*cos(s[2]);
+}
+void xyz2tprVel( Coord x, Coord vx, Coord* dest )
+{
+ Coord s;
+ xyz2tprCoord( x, &s );
+ (*dest)[0] = -1.0f*vx[0]*sin(s[0])+vx[1]*cos(s[0]);
+ (*dest)[1] = vx[0]*sin(s[2])*cos(s[0])+vx[1]*sin(s[2])*sin(s[0])+vx[2]*cos(s[2]);
+ (*dest)[2] = vx[0]*cos(s[2])*cos(s[0])+vx[1]*cos(s[2])*sin(s[0])-vx[2]*sin(s[2]);
+}
+void tpr2xyzVel( Coord s, Coord vs, Coord* dest )
+{
+ (*dest)[0] = vs[1]*sin(s[2])*cos(s[0])+vs[2]*cos(s[2])*cos(s[0])-vs[0]*sin(s[0]);
+ (*dest)[1] = vs[1]*sin(s[2])*sin(s[0])+vs[2]*cos(s[2])*sin(s[0])+vs[0]*cos(s[0]);
+ (*dest)[2] = vs[1]*cos(s[2])-vs[2]*sin(s[2]);
+}
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshElements.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshElements.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshElements.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,886 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Pururav Thoutireddy,
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Pururav Thoutireddy, Staff Scientist, Caltech
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: RemeshElements.c 3259 2006-11-09 20:06:31Z EunseoChoi $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Remesh.h"
+#include "Register.h"
+#include "Utils.h"
+
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <float.h>
+
+
+void _SnacRemesher_InterpolateElements( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get( context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ Element_LocalIndex element_lI;
+ Element_DomainIndex element_dI;
+ Tetrahedra_Index tet_I;
+
+ Element_DomainIndex ellI,ellJ,ellK;
+ Element_DomainIndex nellI = decomp->elementLocal3DCounts[decomp->rank][0];
+ Element_DomainIndex nellJ = decomp->elementLocal3DCounts[decomp->rank][1];
+ Element_DomainIndex nellK = decomp->elementLocal3DCounts[decomp->rank][2];
+ Element_DomainIndex eldI,eldJ,eldK;
+ Element_DomainIndex neldI = decomp->elementDomain3DCounts[0];
+ Element_DomainIndex neldJ = decomp->elementDomain3DCounts[1];
+ Element_DomainIndex neldK = decomp->elementDomain3DCounts[2];
+
+ void Tet_Barycenter( Coord tetCrds[4], Coord center );
+ void createBarycenterGrids( void* _context );
+
+ struct dist_elem_pair { double dist; unsigned int id; };
+ int dist_compare( const void* dist1, const void* dist2 ) {
+ /* double v1 = *(double *)dist1; */
+ /* double v2 = *(double *)dist2; */
+ double v1 = ((struct dist_elem_pair *)dist1)->dist;
+ double v2 = ((struct dist_elem_pair *)dist2)->dist;
+ //return (dist1<dist2) ? -1 : (dist1>dist2) ? 1 : 0;
+ return (v1<v2) ? -1 : (v1>v2) ? 1 : 0;
+ };
+
+ /* Create old and new grids of barycenters */
+ createBarycenterGrids( context );
+
+ /*
+ ** Free any owned arrays that may still exist from the last node interpolation.
+ */
+ FreeArray( meshExt->externalElements );
+ meshExt->nExternalElements = 0;
+
+ /*
+ ** Interpolate all new elements.
+ */
+
+ /* Compute coefficients for barycentric coordinates. */
+ for( eldI = 0; eldI < neldI-1; eldI++ )
+ for( eldJ = 0; eldJ < neldJ-1; eldJ++ )
+ for( eldK = 0; eldK < neldK-1; eldK++ ) {
+ Coord hexCrds[8];
+ Tetrahedra_Index tet_I;
+ Index coef_i;
+
+ /* Old domain grid is constructed: i.e., ghost elements are included in this grid. */
+ element_dI = eldI+eldJ*neldI+eldK*neldI*neldJ;
+
+ /* Eight-node hex defined. */
+ Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI+eldJ*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[1], meshExt->oldBarycenters[eldI+1+eldJ*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[2], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[4], meshExt->oldBarycenters[eldI+eldJ*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[5], meshExt->oldBarycenters[eldI+1+eldJ*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[6], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[7], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
+
+ for(tet_I=0;tet_I<5;tet_I++) {
+ /*
+ [Ta Tb Tc] = [x0-x3 x1-x3 x2-x3]
+ [Td Te Tf] = [y0-y3 y1-y3 y2-y3]
+ [Tg Th Tk] = [z0-z3 z1-z3 z2-z3]
+ */
+ double Ta = hexCrds[TetraToNode[tet_I][0]][0] - hexCrds[TetraToNode[tet_I][3]][0];
+ double Tb = hexCrds[TetraToNode[tet_I][1]][0] - hexCrds[TetraToNode[tet_I][3]][0];
+ double Tc = hexCrds[TetraToNode[tet_I][2]][0] - hexCrds[TetraToNode[tet_I][3]][0];
+ double Td = hexCrds[TetraToNode[tet_I][0]][1] - hexCrds[TetraToNode[tet_I][3]][1];
+ double Te = hexCrds[TetraToNode[tet_I][1]][1] - hexCrds[TetraToNode[tet_I][3]][1];
+ double Tf = hexCrds[TetraToNode[tet_I][2]][1] - hexCrds[TetraToNode[tet_I][3]][1];
+ double Tg = hexCrds[TetraToNode[tet_I][0]][2] - hexCrds[TetraToNode[tet_I][3]][2];
+ double Th = hexCrds[TetraToNode[tet_I][1]][2] - hexCrds[TetraToNode[tet_I][3]][2];
+ double Tk = hexCrds[TetraToNode[tet_I][2]][2] - hexCrds[TetraToNode[tet_I][3]][2];
+
+ double detT = Ta*(Te*Tk-Tf*Th) + Tb*(Tf*Tg-Tk*Td) + Tc*(Td*Th-Te*Tg);
+ /*
+ Li(x,y,z) = a0*x+a1*y+a2*z+a3
+ */
+ /* L1 coeffs */
+ meshExt->barcoef[element_dI].coef[tet_I][0][0] = (Te*Tk-Tf*Th)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][0][1] = (Tc*Th-Tb*Tk)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][0][2] = (Tb*Tf-Tc*Te)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][0][3] = 0.0;
+ /* L2 coeffs */
+ meshExt->barcoef[element_dI].coef[tet_I][1][0] = (Tf*Tg-Td*Tk)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][1][1] = (Ta*Tk-Tc*Tg)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][1][2] = (Tc*Td-Ta*Tf)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][1][3] = 0.0;
+ /* L3 coeffs */
+ meshExt->barcoef[element_dI].coef[tet_I][2][0] = (Td*Th-Te*Tg)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][2][1] = (Tg*Tb-Ta*Th)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][2][2] = (Ta*Te-Tb*Td)/detT;
+ meshExt->barcoef[element_dI].coef[tet_I][2][3] = 0.0;
+ /* L4 not needed because L4 = 1.0 - (L1 + L2 + L3) */
+
+ for(coef_i=0;coef_i<3;coef_i++) {
+ meshExt->barcoef[element_dI].coef[tet_I][0][3] -= meshExt->barcoef[element_dI].coef[tet_I][0][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
+ meshExt->barcoef[element_dI].coef[tet_I][1][3] -= meshExt->barcoef[element_dI].coef[tet_I][1][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
+ meshExt->barcoef[element_dI].coef[tet_I][2][3] -= meshExt->barcoef[element_dI].coef[tet_I][2][coef_i]*hexCrds[TetraToNode[tet_I][3]][coef_i];
+ }
+ }
+ }
+
+ /* First find a containing tet in the grid of old hex's barycenters
+ and compute barycentric coordinates. */
+ for( ellK = 0; ellK < nellK; ellK++ )
+ for( ellJ = 0; ellJ < nellJ; ellJ++ )
+ for( ellI = 0; ellI < nellI; ellI++ ) {
+ unsigned found_tet;
+
+ Element_DomainIndex eldI,eldJ,eldK;
+ Element_DomainIndex neldI = decomp->elementDomain3DCounts[0];
+ Element_DomainIndex neldJ = decomp->elementDomain3DCounts[1];
+ Element_DomainIndex neldK = decomp->elementDomain3DCounts[2];
+ Element_DomainIndex mindI,mindJ,mindK,maxdI,maxdJ,maxdK,searchI;
+
+ double lambda_sqrd = 0.0;
+ double lambda_sqrd_min = 1e+16;
+ Element_DomainIndex closest_dI=0;
+ Tetrahedra_Index closest_tI=0;
+
+ /* Grid of new barycenters is constructed without ghost elements included. */
+ element_lI = ellI+ellJ*nellI+ellK*nellI*nellJ;
+
+ /* Start searching near the element in old barycenter grid
+ of which domain element number is equal to element_lI. */
+ searchI = 2;
+ mindI = (((ellI-searchI)<0)?0:(ellI-searchI));
+ mindJ = (((ellJ-searchI)<0)?0:(ellJ-searchI));
+ mindK = (((ellK-searchI)<0)?0:(ellK-searchI));
+ maxdI = (((ellI+searchI)>=neldI)?(neldI-1):(ellI+searchI));
+ maxdJ = (((ellJ+searchI)>=neldJ)?(neldJ-1):(ellJ+searchI));
+ maxdK = (((ellK+searchI)>=neldK)?(neldK-1):(ellK+searchI));
+ found_tet = 0;
+ for( eldK = mindK; eldK < maxdK; eldK++ ) {
+ for( eldJ = mindJ; eldJ < maxdJ; eldJ++ ) {
+ for( eldI = mindI; eldI < maxdI; eldI++ ) {
+ element_dI = eldI+eldJ*neldI+eldK*neldI*neldJ;
+ for(tet_I=0;tet_I<5;tet_I++) {
+ Index coef_I;
+ double lambda[4];
+ double tol_error = 1e-4;
+ lambda[3] = 1.0;
+ for(coef_I=0;coef_I<3;coef_I++) {
+ lambda[coef_I] =
+ meshExt->newBarycenters[element_lI][0]*meshExt->barcoef[element_dI].coef[tet_I][coef_I][0] +
+ meshExt->newBarycenters[element_lI][1]*meshExt->barcoef[element_dI].coef[tet_I][coef_I][1] +
+ meshExt->newBarycenters[element_lI][2]*meshExt->barcoef[element_dI].coef[tet_I][coef_I][2] +
+ meshExt->barcoef[element_dI].coef[tet_I][coef_I][3];
+ lambda[3] -= lambda[coef_I];
+ }
+ /* Keep track of closest element in case the current new barycenter is outside of the old grid. */
+ for(coef_I=0;coef_I<3;coef_I++)
+ lambda_sqrd += lambda[coef_I]*lambda[coef_I];
+ if( lambda_sqrd < lambda_sqrd_min ) {
+ lambda_sqrd_min = lambda_sqrd;
+ closest_dI = element_dI;
+ closest_tI = tet_I;
+ }
+
+ /* See if the barycenter is inside this tet. */
+ if( (lambda[0] >= -tol_error && lambda[0] <= (1.0+tol_error)) &&
+ (lambda[1] >= -tol_error && lambda[1] <= (1.0+tol_error)) &&
+ (lambda[2] >= -tol_error && lambda[2] <= (1.0+tol_error)) &&
+ (lambda[3] >= -tol_error && lambda[3] <= (1.0+tol_error)) ) {
+ found_tet = 1;
+ memcpy( meshExt->barcord[element_lI].L, lambda, sizeof(double)*4);
+ meshExt->barcord[element_lI].elnum = element_dI;
+ meshExt->barcord[element_lI].tetnum = tet_I;
+ break; /* break tet loop */
+ }
+ }
+ if( found_tet ) break; /* break eldI loop */
+ }
+ if( found_tet ) break; /* break eldJ loop */
+ }
+ if( found_tet ) break; /* break eldK loop */
+ } /* end of domain element search */
+
+ /* see if the point is outside of the old mesh.
+ Assumed is that the current new barycenter is at least closest to "closest_dI" element. */
+ if( !found_tet ) {
+ Index dim_I;
+ Coord hexCrds[8];
+ struct dist_elem_pair dist_apexes[4];
+ double dist_sum;
+ Index apex_I;
+
+ /* Decompose closest_dI into ijk indexes. */
+ eldI = closest_dI % neldI;
+ eldJ = ((closest_dI-eldI)/neldI) % neldJ;
+ eldK = (closest_dI-eldI-eldJ*neldI)/(neldI*neldJ);
+
+ /* Eight-node hex defined. */
+ Vector_Set( hexCrds[0], meshExt->oldBarycenters[eldI+eldJ*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[1], meshExt->oldBarycenters[eldI+1+eldJ*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[2], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[3], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+eldK*neldI*neldJ] );
+ Vector_Set( hexCrds[4], meshExt->oldBarycenters[eldI+eldJ*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[5], meshExt->oldBarycenters[eldI+1+eldJ*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[6], meshExt->oldBarycenters[eldI+1+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
+ Vector_Set( hexCrds[7], meshExt->oldBarycenters[eldI+(eldJ+1)*neldI+(eldK+1)*neldI*neldJ] );
+
+ /* compute distances to tet apexes to find the closest three (supposedly forming the closes face).*/
+ for( apex_I = 0; apex_I < 4; apex_I++ ) {
+ double tmp = 0.0;
+ for( dim_I = 0; dim_I < 3; dim_I++ )
+ tmp += pow((meshExt->newBarycenters[element_lI][dim_I]-hexCrds[TetraToNode[closest_tI][apex_I]][dim_I]),2.0);
+ dist_apexes[apex_I].dist = sqrt(tmp);
+ dist_apexes[apex_I].id = apex_I;
+ }
+ qsort( (void *)dist_apexes, 4, sizeof(struct dist_elem_pair), dist_compare ); /* dist arrary sorted in the ascending order. */
+
+ dist_sum = 0.0;
+ for( apex_I = 0; apex_I < 3; apex_I++ )
+ dist_sum += (1.0/dist_apexes[apex_I].dist);
+
+ found_tet = 1;
+ for( apex_I = 0; apex_I < 3; apex_I++ )
+ meshExt->barcord[element_lI].L[dist_apexes[apex_I].id] = (1.0/dist_apexes[apex_I].dist)/dist_sum;
+ meshExt->barcord[element_lI].L[dist_apexes[3].id] = 0.0;
+ meshExt->barcord[element_lI].elnum = closest_dI;
+ meshExt->barcord[element_lI].tetnum = closest_tI;
+ }
+ } /* end of loop oever new barycenters. */
+
+ /* Finally, ready to interpolation for every element in the new "Local" mesh. */
+ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ )
+ for(tet_I=0;tet_I<5;tet_I++)
+ SnacRemesher_InterpolateElement( context, contextExt,
+ element_lI, tet_I,
+ meshExt->newElements,
+ meshExt->barcord[element_lI].elnum,
+ meshExt->barcord[element_lI].tetnum );
+
+}
+
+void createBarycenterGrids( void* _context ) {
+
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ Element_LocalIndex element_lI;
+ Element_DomainIndex element_dI;
+
+ /* Loop over the new elements. */
+ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ ) {
+ unsigned nEltNodes;
+ Node_DomainIndex* eltNodes;
+
+ /* Extract the element's node indices. Note that there should always be eight of these. */
+ {
+ Element_GlobalIndex gEltInd;
+
+ nEltNodes = 8;
+ eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
+ //element_gI = Mesh_ElementMapLocalToGlobal( mesh, element_lI );
+ nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
+ }
+
+ /* Convert global node indices to local. */
+ {
+ unsigned eltNode_i;
+
+ meshExt->newBarycenters[element_lI][0] = 0.0;
+ meshExt->newBarycenters[element_lI][1] = 0.0;
+ meshExt->newBarycenters[element_lI][2] = 0.0;
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ eltNodes[eltNode_i] = Mesh_NodeMapGlobalToLocal( mesh, eltNodes[eltNode_i] );
+ meshExt->newBarycenters[element_lI][0] += (meshExt->newNodeCoords[eltNodes[eltNode_i]][0]/nEltNodes);
+ meshExt->newBarycenters[element_lI][1] += (meshExt->newNodeCoords[eltNodes[eltNode_i]][1]/nEltNodes);
+ meshExt->newBarycenters[element_lI][2] += (meshExt->newNodeCoords[eltNodes[eltNode_i]][2]/nEltNodes);
+ }
+ }
+ }
+
+ /* Loop over the old elements. */
+ for( element_dI = 0; element_dI < mesh->elementDomainCount; element_dI++ ) {
+ unsigned nEltNodes;
+ Node_DomainIndex* eltNodes;
+ //Element_GlobalIndex element_gI;
+
+ /* Extract the element's node indices. Note that there should always be eight of these. */
+ {
+ Element_GlobalIndex gEltInd;
+
+ nEltNodes = 8;
+ eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
+ //element_gI = Mesh_ElementMapDomainToGlobal( mesh, element_dI );
+ nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
+ }
+
+ /* Convert global node indices to local. */
+ {
+ unsigned eltNode_i;
+
+ meshExt->oldBarycenters[element_dI][0] = 0.0;
+ meshExt->oldBarycenters[element_dI][1] = 0.0;
+ meshExt->oldBarycenters[element_dI][2] = 0.0;
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ eltNodes[eltNode_i] = Mesh_NodeMapGlobalToLocal( mesh, eltNodes[eltNode_i] );
+ meshExt->oldBarycenters[element_dI][0] += (mesh->nodeCoord[eltNodes[eltNode_i]][0]/nEltNodes);
+ meshExt->oldBarycenters[element_dI][1] += (mesh->nodeCoord[eltNodes[eltNode_i]][1]/nEltNodes);
+ meshExt->oldBarycenters[element_dI][2] += (mesh->nodeCoord[eltNodes[eltNode_i]][2]/nEltNodes);
+ }
+ }
+ }
+
+}
+
+void _SnacRemesher_UpdateElements( void* _context ) {
+
+ Snac_Context* context = (Snac_Context*)_context;
+ Element_LocalIndex element_lI;
+
+ /* Update all the elements, and in the process work out this processor's minLengthScale */
+ for( element_lI = 0; element_lI < context->mesh->elementLocalCount; element_lI++ ) {
+ double elementMinLengthScale;
+
+ KeyCall( context, context->updateElementK, Snac_UpdateElementMomentum_CallCast* )
+ ( KeyHandle(context,context->updateElementK),
+ context,
+ element_lI,
+ &elementMinLengthScale );
+ if( elementMinLengthScale < context->minLengthScale ) {
+ context->minLengthScale = elementMinLengthScale;
+ }
+ }
+}
+
+
+/*
+ Interpolate an element's tetrahedra.
+ Note that srcEltInd and srcTetInd are those of the old barycenter grid.
+*/
+void _SnacRemesher_InterpolateElement( void* _context,
+ Element_LocalIndex dstEltInd,
+ Tetrahedra_Index tetInd,
+ Snac_Element* dstEltArray,
+ Element_DomainIndex srcEltInd,
+ Tetrahedra_Index srcTetInd )
+{
+
+ Snac_Context* context = (Snac_Context*)_context;
+ Snac_Element* dstElt = (Snac_Element*)ExtensionManager_At( context->mesh->elementExtensionMgr,
+ dstEltArray,
+ dstEltInd );
+ Element_DomainIndex eltdI[8],eldI,eldJ,eldK;
+ Tetrahedra_Index srcTet[8];
+ double dblMaterial_I;
+
+ /* Decompose srcEltInd into ijk indexes. */
+ eldI = srcEltInd % neldI;
+ eldJ = ((srcEltInd-eldI)/neldI) % neldJ;
+ eldK = (srcEltInd-eldI-eldJ*neldI)/(neldI*neldJ);
+
+ /* Eight-node hex defined on the old barycenter grid. */
+ eltdI[0] = srcEltInd;
+ eltdI[1] = (eldI+1) + eldJ*neldI + eldK*neldI*neldJ;
+ eltdI[2] = (eldI+1) + (eldJ+1)*neldI + eldK*neldI*neldJ;
+ eltdI[3] = eldI + (eldJ+1)*neldI + eldK*neldI*neldJ;
+ eltdI[4] = eldI + eldJ*neldI + (eldK+1)*neldI*neldJ;
+ eltdI[5] = (eldI+1) + eldJ*neldI + (eldK+1)*neldI*neldJ;
+ eltdI[6] = (eldI+1) + (eldJ+1)*neldI + (eldK+1)*neldI*neldJ;
+ eltdI[7] = eldI + (eldJ+1)*neldI + (eldK+1)*neldI*neldJ;
+
+ memset( dstElt->tetra[tetInd].strain, 0, sizeof(double)*3*3 );
+ memset( dstElt->tetra[tetInd].stress, 0, sizeof(double)*3*3 );
+ dblMaterial_I = 0.0;
+ dstElt->tetra[dstTetInd].density = 0.0;
+ for(coef_I=0;coef_I<4;coef_I++) {
+ /* The actual src elements are the apexes of the tet in the old barycenter grid. */
+ Snac_Element* srcElt = Snac_Element_At( context, eltdI[TetraToNode[srcTetInd][coef_I]] );
+
+ dstElt->tetra[tetInd].strain[0][0] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[0][0];
+ dstElt->tetra[tetInd].strain[1][1] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[1][1];
+ dstElt->tetra[tetInd].strain[2][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[2][2];
+ dstElt->tetra[tetInd].strain[0][1] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[0][1];
+ dstElt->tetra[tetInd].strain[0][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[0][2];
+ dstElt->tetra[tetInd].strain[1][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].strain[1][2];
+
+ dstElt->tetra[tetInd].stress[0][0] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[0][0];
+ dstElt->tetra[tetInd].stress[1][1] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[1][1];
+ dstElt->tetra[tetInd].stress[2][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[2][2];
+ dstElt->tetra[tetInd].stress[0][1] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[0][1];
+ dstElt->tetra[tetInd].stress[0][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[0][2];
+ dstElt->tetra[tetInd].stress[1][2] += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].stress[1][2];
+
+ dblMaterial_I += meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].material_I;
+ dstElt->tetra[dstTetInd].density = meshExt->barcord[element_lI].L[coef_I]*srcElt->tetra[tetInd].density;
+ }
+ dstElt->tetra[dstTetInd].material_I = (Material_Index)dblMaterial_I;
+
+}
+
+
+#if 0
+void _SnacRemesher_InterpolateElement( void* _context,
+ Element_LocalIndex dstEltInd,
+ Tetrahedra_Index dstTetInd,
+ Snac_Element* dstEltArray,
+ Element_DomainIndex srcEltInd,
+ Tetrahedra_Index srcTetInd )
+{
+
+ Snac_Context* context = (Snac_Context*)_context;
+ Snac_Element* dstElt = (Snac_Element*)ExtensionManager_At( context->mesh->elementExtensionMgr,
+ dstEltArray,
+ dstEltInd );
+ Snac_Element* srcElt = Snac_Element_At( context, srcEltInd );
+
+ /* Copy the whole structure from the nearest tet in the old mesh. */
+ memcpy( &(dstElt->tetra[dstTetInd]), &(srcElt->tetra[srcTetInd]), sizeof(Snac_Element_Tetrahedra) );
+
+}
+#endif
+
+
+/*
+** Calculate the barycenter of a tetrahedron.
+*/
+
+void Tet_Barycenter( Coord tetCrds[4], Coord center ) {
+ unsigned tet_i;
+
+ center[0] = tetCrds[0][0];
+ center[1] = tetCrds[0][1];
+ center[2] = tetCrds[0][2];
+
+ for( tet_i = 1; tet_i < 4; tet_i++ ) {
+ center[0] += tetCrds[tet_i][0];
+ center[1] += tetCrds[tet_i][1];
+ center[2] += tetCrds[tet_i][2];
+ }
+
+ center[0] *= 0.25;
+ center[1] *= 0.25;
+ center[2] *= 0.25;
+}
+
+
+
+
+
+#if 0
+
+#define DIM 3
+
+#ifndef SQR
+ #define SQR(a) ((a)*(a))
+#endif
+#ifndef VECDIST3
+ #define VECDIST3(a,b) ( sqrt( SQR((a)[0]-(b)[0]) + SQR((a)[1]-(b)[1]) + SQR((a)[2]-(b)[2]) ) )
+#endif
+
+void _SnacRemesher_InterpolateElement(
+ void* _context,
+ Element_LocalIndex element_lI,
+ Tetrahedra_Index tetra_I,
+ Element_LocalIndex fromElement_lI,
+ Partition_Index fromElement_rn_I,
+ Element_ShadowIndex fromElement_sI,
+ Tetrahedra_Index fromTetra_I,
+ Snac_Element* newElement,
+ Snac_Element** shadowElement )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ Snac_Element* element = (Snac_Element*)ExtensionManager_At(
+ context->mesh->elementExtensionMgr,
+ newElement,
+ element_lI );
+ Snac_Element* fromElement;
+
+ /* Deference source element (local/shadow) */
+ if( fromElement_lI < context->mesh->elementLocalCount ) {
+ fromElement = Snac_Element_At( context, fromElement_lI );
+ }
+ else {
+ fromElement = (Snac_Element*)ExtensionManager_At(
+ context->mesh->elementExtensionMgr,
+ shadowElement[fromElement_rn_I],
+ fromElement_sI );
+ }
+
+ element->tetra[tetra_I].strain[0][0] = fromElement->tetra[fromTetra_I].strain[0][0];
+ element->tetra[tetra_I].strain[1][1] = fromElement->tetra[fromTetra_I].strain[1][1];
+ element->tetra[tetra_I].strain[2][2] = fromElement->tetra[fromTetra_I].strain[2][2];
+ element->tetra[tetra_I].strain[0][1] = fromElement->tetra[fromTetra_I].strain[0][1];
+ element->tetra[tetra_I].strain[0][2] = fromElement->tetra[fromTetra_I].strain[0][2];
+ element->tetra[tetra_I].strain[1][2] = fromElement->tetra[fromTetra_I].strain[1][2];
+
+ element->tetraStress[tetra_I][0][0] = fromElement->tetraStress[fromTetra_I][0][0];
+ element->tetraStress[tetra_I][1][1] = fromElement->tetraStress[fromTetra_I][1][1];
+ element->tetraStress[tetra_I][2][2] = fromElement->tetraStress[fromTetra_I][2][2];
+ element->tetraStress[tetra_I][0][1] = fromElement->tetraStress[fromTetra_I][0][1];
+ element->tetraStress[tetra_I][0][2] = fromElement->tetraStress[fromTetra_I][0][2];
+ element->tetraStress[tetra_I][1][2] = fromElement->tetraStress[fromTetra_I][1][2];
+}
+
+
+void _SnacRemesher_InterpolateElements( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = (Mesh*)context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ MeshLayout* layout = mesh->layout;
+ HexaMD* decomp = (HexaMD*)layout->decomp;
+ Topology* topology = layout->elementLayout->topology;
+ ElementLayout* elementLayout = layout->elementLayout;
+ Element_LocalIndex element_lI;
+
+ Partition_Index rn_I;
+ Coord** sbc;
+ double* xbc;
+ int n,i,d;
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ /* Calculate the barycentric coords for each tetra of the old mesh */
+ xbc = calloc( DIM * Tetrahedra_Count * mesh->elementLocalCount, sizeof(double) );
+ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ ) {
+ Tetrahedra_Index tetra_I;
+
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) {
+ double *x0;
+ double *x1;
+ double *x2;
+ double *x3;
+
+ x0=Snac_Element_NodeCoord( context, element_lI, TetraToNode[tetra_I][0] );
+ x1=Snac_Element_NodeCoord( context, element_lI, TetraToNode[tetra_I][1] );
+ x2=Snac_Element_NodeCoord( context, element_lI, TetraToNode[tetra_I][2] );
+ x3=Snac_Element_NodeCoord( context, element_lI, TetraToNode[tetra_I][3] );
+ for( d = 0; d < DIM; d++ ) {
+ xbc[(element_lI * Tetrahedra_Count + tetra_I) * DIM + d]= 0.25 * (x0[d] + x1[d] + x2[d] + x3[d]);
+ }
+ }
+ }
+
+ /* Calculate the barycentric coords for each tetra of the shadows */
+ sbc = (Coord**)malloc( sizeof(Coord*) * meshExt->neighbourRankCount );
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sI;
+
+ sbc[rn_I] = (Coord*)malloc( sizeof(Coord) * meshExt->shadowElementRemoteCount[rn_I] * Tetrahedra_Count );
+
+ for( element_sI = 0; element_sI < meshExt->shadowElementRemoteCount[rn_I]; element_sI++ ) {
+ Element_GlobalIndex element_gI = meshExt->shadowElementRemoteArray[rn_I][element_sI];
+ Node_GlobalIndex elementNode[8];
+ Coord coord[8];
+ Element_NodeIndex en_I;
+ Tetrahedra_Index tetra_I;
+
+ /* Build a temporary table of the coordinates of the points of this element. */
+ _HexaEL_BuildCornerIndices( elementLayout, element_gI, elementNode );
+ for( en_I = 0; en_I < 8; en_I++ ) {
+ Node_GlobalIndex node_gI = elementNode[en_I];
+ Node_LocalIndex node_lI = Mesh_NodeMapGlobalToLocal( mesh, node_gI );
+
+ /* Grab the coordinates of the element node. We do this by working out if the node is local and if
+ so, directly copying the value from the mesh. If it isn't, it'll be in the shadow arrays...
+ search for it and copy it. */
+ if( node_lI < meshExt->nodeLocalCount ) {
+ coord[en_I][0] = mesh->nodeCoord[node_lI][0];
+ coord[en_I][1] = mesh->nodeCoord[node_lI][1];
+ coord[en_I][2] = mesh->nodeCoord[node_lI][2];
+ }
+ else {
+ /*Partition_Index rn_I2;
+
+ for( rn_I2 = 0; rn_I2 < meshExt->neighbourRankCount; rn_I2++ ) {*/
+ Node_ShadowIndex node_sI;
+
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gI == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ coord[en_I][0] = meshExt->shadowNodeRemoteCoord[rn_I][node_sI][0];
+ coord[en_I][1] = meshExt->shadowNodeRemoteCoord[rn_I][node_sI][1];
+ coord[en_I][2] = meshExt->shadowNodeRemoteCoord[rn_I][node_sI][2];
+ }
+ }
+ /*}*/
+ }
+ }
+
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) {
+ for( d = 0; d < DIM; d++ ) {
+ sbc[rn_I][element_sI * Tetrahedra_Count + tetra_I][d] = 0.25 * (
+ coord[TetraToNode[tetra_I][0]][d] +
+ coord[TetraToNode[tetra_I][1]][d] +
+ coord[TetraToNode[tetra_I][2]][d] +
+ coord[TetraToNode[tetra_I][3]][d] );
+ }
+ }
+ }
+ }
+
+ /* For each tetrahedra of the new mesh, calculate barycentric coords */
+ for( element_lI = 0; element_lI < context->mesh->elementLocalCount; element_lI++ ) {
+ Tetrahedra_Index tetra_I;
+ Element_NeighbourIndex* en = mesh->elementNeighbourTbl[element_lI];
+ Element_NeighbourIndex enCount = mesh->elementNeighbourCountTbl[element_lI];
+
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) {
+ Element_NeighbourIndex en_I;
+ Element_LocalIndex closest_element;
+ Tetrahedra_Index closest_tetra;
+ Element_ShadowIndex closest_sElement;
+ Partition_Index closest_rn;
+ double newxc[3];
+ double oldxc[3];
+ double selfdist;
+ Tetrahedra_Index tetra_J;
+ double dist2;
+ double dist;
+
+ dist2 = selfdist = DBL_MAX;
+
+ /* Calculation of the barycenter for the tetra of new mesh */
+ memset( newxc, 0, sizeof(double) * 3 );
+ for( i = 0; i < 4; i++ ) {
+ n = TetraToNode[tetra_I][i];
+ for( d = 0; d < DIM; d++) {
+ newxc[d]+=0.25 * meshExt->newNodeCoord[mesh->elementNodeTbl[element_lI][n]][d];
+ }
+ }
+
+ /* Find the best tetra (in the sense of barycenter distance) of this element in the old mesh... this
+ will be our starting-point/initial-compare. */
+ closest_element = closest_tetra = 0;
+ closest_rn = (unsigned)-1;
+ for( tetra_J = 0; tetra_J < Tetrahedra_Count; tetra_J++ ) {
+ for( d = 0; d < DIM; d++ ){
+ oldxc[d] = xbc[(element_lI * Tetrahedra_Count + tetra_J) * DIM + d];
+ }
+ dist = VECDIST3( newxc, oldxc );
+ if( tetra_I == tetra_J ){
+ selfdist = dist;
+ }
+ if( dist2 > dist ) {
+ closest_element = element_lI;
+ closest_tetra = tetra_J;
+ dist2 = dist;
+ }
+ }
+
+ /* Find the best tetra (in the sense of barycenter distance) of this element's neighbours in the old
+ mesh, using the self-comparison above as a starting-point. */
+ for( en_I = 0; en_I < enCount; en_I++ ) {
+ Element_LocalIndex enElement_lI = en[en_I];
+
+ /* The element neighbour is a local element */
+ if( enElement_lI < mesh->elementLocalCount ) {
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Element %03u's neighbour %02u (g%03u) is a local neighbour\n",
+ mesh->elementL2G[element_lI],
+ en_I,
+ mesh->elementL2G[enElement_lI] );
+
+ for( tetra_J = 0; tetra_J < Tetrahedra_Count; tetra_J++ ) {
+ for( d = 0; d < DIM; d++ ) {
+ oldxc[d] = xbc[(enElement_lI * Tetrahedra_Count + tetra_J) * DIM + d];
+ }
+ dist = VECDIST3( newxc, oldxc );
+ if( dist2 > dist ) {
+ closest_element = enElement_lI;
+ closest_tetra = tetra_J;
+ dist2 = dist;
+ }
+ }
+ }
+ else { /* The element neighbour is a shadow element or non-existant */
+ Element_GlobalIndex tmpEN[mesh->elementNeighbourCountTbl[element_lI]];
+ Element_GlobalIndex element_gI = decomp->elementMapLocalToGlobal(
+ decomp,
+ element_lI );
+ Element_GlobalIndex enElement_gI;
+
+ topology->buildNeighbours( topology, element_gI, tmpEN );
+ enElement_gI = tmpEN[en_I];
+
+ /* The element neighbour is a shadow */
+ if( enElement_gI < meshExt->elementGlobalCount ) {
+ Bool found;
+
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Element %03u's neighbour %02u (g%03u) is a shadow neighbour\n",
+ mesh->elementL2G[element_lI],
+ en_I,
+ enElement_gI );
+
+ /* Search through the shadow lists for the element */
+ found = False;
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount && !found; rn_I++ ) {
+ Element_ShadowIndex element_sI;
+
+ for(
+ element_sI = 0;
+ element_sI < meshExt->shadowElementRemoteCount[rn_I] && !found;
+ element_sI++ ) {
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "enElement_gI == meshExt->ShadowElementArrayRemote[%u][%u] => %u == %u\n",
+ rn_I,
+ element_sI,
+ enElement_gI,
+ meshExt->shadowElementRemoteArray[rn_I][element_sI] );
+
+ if( enElement_gI == meshExt->shadowElementRemoteArray[rn_I][element_sI] ) {
+ /* Element found in shadow lists. Find if it has a closer
+ tetra */
+ for( tetra_J = 0; tetra_J < Tetrahedra_Count; tetra_J++ ) {
+ for( d = 0; d < DIM; d++ ) {
+ oldxc[d] = sbc[rn_I][element_sI * Tetrahedra_Count + tetra_J][d];
+ }
+ dist = VECDIST3( newxc, oldxc );
+ if( dist2 > dist ) {
+ closest_rn = rn_I;
+ closest_sElement = element_sI;
+ closest_element = (unsigned)-1;
+ closest_tetra = tetra_J;
+ dist2 = dist;
+ }
+ }
+ found = True;
+ }
+ }
+ }
+
+ /* Essentially the enElement_gI should be found in the shadow listings, else there
+ is a big coding error! */
+ assert( found );
+ }
+ else {
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Element g%03u's neighbour %02u (g%03u) is out of bounds\n",
+ mesh->elementL2G[element_lI],
+ en_I,
+ enElement_gI );
+ continue;
+ }
+ }
+ }
+
+ if( dist2 > selfdist ) {
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Distance between barycentres of old and new tetrahadras cannot be bigger than" );
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "barycentric distance of the same tetrahedra in old and new mesh\n\n" );
+ }
+
+
+ /* transfer */
+ SnacRemesher_InterpolateElement(
+ context,
+ contextExt,
+ element_lI,
+ tetra_I,
+ closest_element,
+ closest_rn,
+ closest_sElement,
+ closest_tetra,
+ meshExt->newElement,
+ meshExt->shadowElementRemote );
+ }
+ }
+
+#if 0
+ for( element_lI = 0; element_lI < mesh->elementLocalCount; element_lI++ ) {
+ Snac_Element* element = (Snac_Element*)Extension_At(
+ context->mesh->elementExtensionMgr,
+ meshExt->newElement,
+ element_lI );
+ Tetrahedra_Index tetra_I;
+
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) {
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Element-tetra g%03u-%u: stress: %g %g %g %g %g %g\n",
+ mesh->elementL2G[element_lI],
+ tetra_I,
+ element->tetraStress[tetra_I][0][0],
+ element->tetraStress[tetra_I][1][1],
+ element->tetraStress[tetra_I][2][2],
+ element->tetraStress[tetra_I][0][1],
+ element->tetraStress[tetra_I][0][2],
+ element->tetraStress[tetra_I][1][2] );
+ Journal_DPrintf(
+ contextExt->debugElements,
+ "Element-tetra g%03u-%u: strain: %g %g %g %g %g %g\n",
+ mesh->elementL2G[element_lI],
+ tetra_I,
+ element->tetra[tetra_I].strain[0][0],
+ element->tetra[tetra_I].strain[1][1],
+ element->tetra[tetra_I].strain[2][2],
+ element->tetra[tetra_I].strain[0][1],
+ element->tetra[tetra_I].strain[0][2],
+ element->tetra[tetra_I].strain[1][2] );
+ }
+ }
+#endif
+
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ free( sbc[rn_I] );
+ }
+ free( sbc );
+ free( xbc );
+}
+
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshNodes.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshNodes.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/RemeshNodes.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,1537 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Pururav Thoutireddy,
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Pururav Thoutireddy, Staff Scientist, Caltech
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: RemeshNodes.c 3259 2006-11-09 20:06:31Z EunseoChoi $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Remesh.h"
+#include "Register.h"
+#include "Utils.h"
+
+#include <string.h>
+#include <assert.h>
+#include <float.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_linalg.h>
+
+
+void _SnacRemesher_InterpolateNodes( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ Node_LocalIndex newNode_i;
+ IndexSet* extNodes;
+
+ void interpolateNode( void* _context, Node_LocalIndex newNodeInd, Element_DomainIndex dEltInd );
+ void SPR( void* _context );
+
+ /*
+ ** Free any owned arrays that may still exist from the last node interpolation.
+ */
+
+ FreeArray( meshExt->externalNodes );
+ meshExt->nExternalNodes = 0;
+
+
+ /*
+ ** Populate arrays for recovered fields using the SPR method.
+ */
+ SPR( context );
+
+ /*
+ ** Scoot over all the new nodes and find the old element in which each one resides, then interpolate.
+ */
+
+ /* Create an index set for storing any external nodes. */
+ extNodes = IndexSet_New( mesh->nodeLocalCount );
+
+ for( newNode_i = 0; newNode_i < mesh->nodeLocalCount; newNode_i++ ) {
+ Node_LocalIndex dNodeInd;
+ unsigned nElements;
+ Element_DomainIndex* elements;
+ Coord newPoint;
+ unsigned elt_i;
+
+ /* Extract the new node's coordinate. */
+ Vector_Set( newPoint, meshExt->newNodeCoords[newNode_i] );
+
+ /* Find the closest old node. */
+ dNodeInd = findClosestNode( context, newPoint, newNode_i );
+
+ /* Grab incident elements. */
+ {
+ Node_GlobalIndex gNodeInd;
+
+ gNodeInd = Mesh_NodeMapDomainToGlobal( mesh, dNodeInd );
+ nElements = nLayout->nodeElementCount( nLayout, gNodeInd );
+ if( nElements ) {
+ elements = Memory_Alloc_Array( Element_DomainIndex, nElements, "SnacRemesher" );
+ nLayout->buildNodeElements( nLayout, gNodeInd, elements );
+ }
+ else {
+ elements = NULL;
+ }
+ }
+
+ /* Convert global element indices to domain. */
+ for( elt_i = 0; elt_i < nElements; elt_i++ ) {
+ elements[elt_i] = Mesh_ElementMapGlobalToDomain( mesh, elements[elt_i] );
+ }
+
+ /* Which of the incident elements contains the node? */
+ for( elt_i = 0; elt_i < nElements; elt_i++ ) {
+ if( elements[elt_i] >= mesh->elementDomainCount ) {
+ continue;
+ }
+
+ if( pointInElement( context, newPoint, elements[elt_i] ) ) {
+ break;
+ }
+ }
+
+ /* Did we find the element? */
+ if( elt_i < nElements ) {
+ /* If so, call a function to locate the tetrahedra and interpolate. */
+ interpolateNode( context, newNode_i, elements[elt_i] );
+ }
+ else {
+ /* If not, then the new node finds itself outside the old mesh. In this scenario, we cannot interpolate
+ the nodal values with any accuracy (without knowing more about the physical problem). So, we will leave
+ the node with its old values and mark this node as not being interpolated so the user may deal with it. */
+
+ /* Stash the node index. */
+ IndexSet_Add( extNodes, newNode_i );
+
+ /* Copy across the old value. Note that this should be done using some other provided copy method. */
+ memcpy( (unsigned char*)meshExt->newNodes + newNode_i * mesh->nodeExtensionMgr->finalSize,
+ (unsigned char*)mesh->node + newNode_i * mesh->nodeExtensionMgr->finalSize,
+ mesh->nodeExtensionMgr->finalSize );
+ /* assert(0); */
+ }
+
+ /* Free element array. */
+ FreeArray( elements );
+ }
+
+ /* Dump the external nodes and delete the set. */
+ IndexSet_GetMembers( extNodes, &meshExt->nExternalNodes, &meshExt->externalNodes );
+ Stg_Class_Delete( extNodes );
+}
+
+
+#define det3_sub( x1, x2, x3 ) ( \
+ (x1)[0] * ( (x2)[1] * (x3)[2] - (x3)[1] * (x2)[2] ) - \
+ (x1)[1] * ( (x2)[0] * (x3)[2] - (x3)[0] * (x2)[2] ) + \
+ (x1)[2] * ( (x2)[0] * (x3)[1] - (x3)[0] * (x2)[1] ) )
+
+
+#define TetrahedronVolume( x1, x2, x3, x4 ) ( \
+ ( det3_sub( (x2), (x3), (x4) ) - \
+ det3_sub( (x1), (x3), (x4) ) + \
+ det3_sub( (x1), (x2), (x4) ) - \
+ det3_sub( (x1), (x2), (x3) ) \
+ ) / 6.0f )
+
+
+#define isLargerThanZero( val, tol ) \
+ (((val) >= -(tol) && (val) <= (tol)) ? 0.0 : (val))
+
+
+#define isLargerThanZero2( val, ref, tol ) \
+ (((val) >= -fabs( ref ) * (tol) && (val) <= fabs( ref ) * tol) ? 0.0 : (val))
+
+
+void interpolateNode( void* _context, Node_LocalIndex newNodeInd, Element_DomainIndex dEltInd ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get( context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get( context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ unsigned nEltNodes;
+ Node_DomainIndex* eltNodes;
+ Coord newNodeCoord;
+ Coord crds[8];
+ double weights[4];
+ unsigned tetNodeInds[4];
+ unsigned eltNode_i;
+
+ /* Extract the element's node indices. Note that there should always be eight of these. */
+ {
+ Element_GlobalIndex gEltInd;
+
+ nEltNodes = 8;
+ eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
+ gEltInd = Mesh_ElementMapDomainToGlobal( mesh, dEltInd );
+ nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
+ }
+
+ /* Convert global node indices to domain. */
+ {
+ unsigned eltNode_i;
+
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ eltNodes[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, eltNodes[eltNode_i] );
+ }
+ }
+
+ /* Extract the new node's coordinate. */
+ Vector_Set( newNodeCoord, meshExt->newNodeCoords[newNodeInd] );
+
+ /* Copy coordinates. */
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ )
+ memcpy( crds[eltNode_i], mesh->nodeCoord[eltNodes[eltNode_i]], sizeof(Coord) );
+
+ if( !_HexaEL_FindTetBarycenter( crds, newNodeCoord, weights, tetNodeInds, INCLUSIVE_UPPER_BOUNDARY, NULL, 0 ) )
+ abort();
+
+ SnacRemesher_InterpolateNode( context, contextExt,
+ newNodeInd, dEltInd, 0,
+ tetNodeInds, weights,
+ meshExt->newNodes );
+
+#if 0
+ /* Loop over 10 sub tets in a brick element, work out the tetra it is in. */
+ for( tet_i = 0; tet_i < nTets; tet_i++ ) {
+ Coord tCrds[4];
+ double TOL = 0.0;
+
+ /* Extract the tetrahedron's coordinates. */
+ Vector_Set( tCrds[0], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 0]]] );
+ Vector_Set( tCrds[1], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 1]]] );
+ Vector_Set( tCrds[2], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 2]]] );
+ Vector_Set( tCrds[3], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 3]]] );
+
+ dett = TetrahedronVolume( tCrds[0], tCrds[1], tCrds[2], tCrds[3] );
+ det[0] = TetrahedronVolume( tCrds[1], tCrds[3], tCrds[2], newNodeCoord );
+ det[1] = TetrahedronVolume( tCrds[2], tCrds[3], tCrds[0], newNodeCoord );
+ det[2] = TetrahedronVolume( tCrds[0], tCrds[3], tCrds[1], newNodeCoord );
+ det[3] = TetrahedronVolume( tCrds[0], tCrds[1], tCrds[2], newNodeCoord );
+
+ dett = isLargerThanZero( dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ /* TODO: Convert to a journal command. */
+ /* Found if all det are greater than zero. */
+ Journal_Firewall( (dett != 0.0 ), "processor %d: element_lI=%d tetra=%d dett is zero!!\napexes: (%e %e %e) (%e %e %e) (%e %e %e) (%e %e %e)\nnewNodeCoord=(%e %e %e)\n",
+ context->rank, dEltInd, tet_i,
+ tCrds[0][0],tCrds[0][1],tCrds[0][2],tCrds[1][0],tCrds[1][1],tCrds[1][2],
+ tCrds[2][0],tCrds[2][1],tCrds[2][2],tCrds[3][0],tCrds[3][1],tCrds[3][2],
+ newNodeCoord[0],newNodeCoord[0],newNodeCoord[0]);
+ if ( det[0] >= 0.0 && det[1] >= 0.0 && det[2] >= 0.0 && det[3] >= 0.0 ) {
+ break;
+ }
+ }
+
+ /* Did we find the tetrahedron? */
+ if( tet_i < nTets ) {
+ Node_DomainIndex tetNodeInds[4];
+ double shape[4];
+ unsigned tNode_i;
+
+ /* Calculate the shape funcs and remap the tetrahedron node indices. */
+ for( tNode_i = 0; tNode_i < 4; tNode_i++ ) {
+ shape[tNode_i] = det[tNode_i] / dett;
+ tetNodeInds[tNode_i] = eltNodes[nSub[tet_i * 4 + tNode_i]];
+ }
+
+ /* Interpolate the node. */
+
+ /*
+ ** This is where we should be calling the entry points for node interpolation.
+ */
+
+ SnacRemesher_InterpolateNode( context, contextExt,
+ newNodeInd, dEltInd, tet_i,
+ tetNodeInds, shape,
+ meshExt->newNodes );
+ }
+ else {
+ /* If not, then something unpleasant is going on, and I don't know what it is. */
+ for( tet_i = 0; tet_i < nTets; tet_i++ ) {
+ Coord tCrds[4];
+ double TOL = 0.0;
+
+ /* Extract the tetrahedron's coordinates. */
+ Vector_Set( tCrds[0], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 0]]] );
+ Vector_Set( tCrds[1], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 1]]] );
+ Vector_Set( tCrds[2], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 2]]] );
+ Vector_Set( tCrds[3], mesh->nodeCoord[eltNodes[nSub[tet_i * 4 + 3]]] );
+
+ dett = TetrahedronVolume( tCrds[0], tCrds[1], tCrds[2], tCrds[3] );
+ det[0] = TetrahedronVolume( tCrds[1], tCrds[3], tCrds[2], newNodeCoord );
+ det[1] = TetrahedronVolume( tCrds[2], tCrds[3], tCrds[0], newNodeCoord );
+ det[2] = TetrahedronVolume( tCrds[0], tCrds[3], tCrds[1], newNodeCoord );
+ det[3] = TetrahedronVolume( tCrds[0], tCrds[1], tCrds[2], newNodeCoord );
+
+ dett = isLargerThanZero( dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ Journal_Printf( context->debug, "processor %d: element_lI=%d/%d tetra=%d\napexes: (%e %e %e) (%e %e %e) (%e %e %e) (%e %e %e)\nnewNodeCoord=(%e %e %e) dets: %e %e %e %e (%e)\n\n",
+ context->rank, dEltInd, mesh->elementDomainCount,tet_i,
+ tCrds[0][0],tCrds[0][1],tCrds[0][2],tCrds[1][0],tCrds[1][1],tCrds[1][2],
+ tCrds[2][0],tCrds[2][1],tCrds[2][2],tCrds[3][0],tCrds[3][1],tCrds[3][2],
+ newNodeCoord[0],newNodeCoord[1],newNodeCoord[2],det[0],det[1],det[2],det[3],dett);
+
+ }
+ Journal_Firewall( 0, "processor %d: element_lI=%d tetra=%d failed to interpolate although a matching element was found!!\n",
+ context->rank, dEltInd, tet_i );
+ }
+#endif
+
+ /* Free the element node array. */
+ FreeArray( eltNodes );
+}
+
+
+/*
+** Interpolate an individual node using a cartesian method or a spherical method.
+*/
+
+void _SnacRemesher_InterpolateNode( void* _context,
+ unsigned nodeInd, unsigned elementInd, unsigned tetInd,
+ unsigned* tetNodeInds, double* weights,
+ Snac_Node* dstNodes )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ Snac_Node* dstNode = (Snac_Node*)ExtensionManager_At( context->mesh->nodeExtensionMgr,
+ dstNodes,
+ nodeInd );
+ unsigned tetNode_i;
+
+ /* Extract the element's node indices. Note that there should always be eight of these. */
+ Node_DomainIndex* eltNodes;
+ unsigned int nEltNodes = 8;
+ {
+ Element_GlobalIndex gEltInd;
+
+ eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
+ gEltInd = Mesh_ElementMapDomainToGlobal( mesh, elementInd );
+ nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
+ }
+
+ /* Convert global node indices to local. */
+ {
+ unsigned eltNode_i;
+
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ eltNodes[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, eltNodes[eltNode_i] );
+ }
+ }
+
+ /* Clear the velocity. */
+ dstNode->velocity[0] = 0.0;
+ dstNode->velocity[1] = 0.0;
+ dstNode->velocity[2] = 0.0;
+
+ dstNode->strainSPR[0] = 0.0;
+ dstNode->strainSPR[1] = 0.0;
+ dstNode->strainSPR[2] = 0.0;
+ dstNode->strainSPR[3] = 0.0;
+ dstNode->strainSPR[4] = 0.0;
+ dstNode->strainSPR[5] = 0.0;
+
+ dstNode->stressSPR[0] = 0.0;
+ dstNode->stressSPR[1] = 0.0;
+ dstNode->stressSPR[2] = 0.0;
+ dstNode->stressSPR[3] = 0.0;
+ dstNode->stressSPR[4] = 0.0;
+ dstNode->stressSPR[5] = 0.0;
+
+ /* Loop over each contributing node. */
+ for( tetNode_i = 0; tetNode_i < 4; tetNode_i++ ) {
+ Snac_Node* srcNode;
+
+ /* Where is this contibution coming from? */
+
+ srcNode = Snac_Node_At( context, eltNodes[tetNodeInds[tetNode_i]] );
+
+ /* Add the contribution. */ // TODO: Do spherical part.
+ dstNode->velocity[0] += srcNode->velocity[0] * weights[tetNode_i];
+ dstNode->velocity[1] += srcNode->velocity[1] * weights[tetNode_i];
+ dstNode->velocity[2] += srcNode->velocity[2] * weights[tetNode_i];
+
+ dstNode->strainSPR[0] += srcNode->strainSPR[0] * weights[tetNode_i];
+ dstNode->strainSPR[1] += srcNode->strainSPR[1] * weights[tetNode_i];
+ dstNode->strainSPR[2] += srcNode->strainSPR[2] * weights[tetNode_i];
+ dstNode->strainSPR[3] += srcNode->strainSPR[3] * weights[tetNode_i];
+ dstNode->strainSPR[4] += srcNode->strainSPR[4] * weights[tetNode_i];
+ dstNode->strainSPR[5] += srcNode->strainSPR[5] * weights[tetNode_i];
+
+ dstNode->stressSPR[0] += srcNode->stressSPR[0] * weights[tetNode_i];
+ dstNode->stressSPR[1] += srcNode->stressSPR[1] * weights[tetNode_i];
+ dstNode->stressSPR[2] += srcNode->stressSPR[2] * weights[tetNode_i];
+ dstNode->stressSPR[3] += srcNode->stressSPR[3] * weights[tetNode_i];
+ dstNode->stressSPR[4] += srcNode->stressSPR[4] * weights[tetNode_i];
+ dstNode->stressSPR[5] += srcNode->stressSPR[5] * weights[tetNode_i];
+
+ }
+}
+
+
+void SPR( void* _context )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ Node_LocalIndex node_lI;
+
+ /* Populate field variables by SPR */
+ for( node_lI = 0; node_lI < mesh->nodeLocalCount; node_lI++ ) {
+ Snac_Node* node = Snac_Node_At( context, node_lI );
+ Coord* coord = Snac_NodeCoord_P( context, node_lI );
+ Index nodeElementCount = context->mesh->nodeElementCountTbl[node_lI];
+ Index nodeElement_I;
+ Element_DomainIndex* elements;
+ gsl_matrix* matA;
+ gsl_vector* vecaStrain[6];
+ gsl_vector* vecaStress[6];
+ gsl_vector* vecaplStrain;
+ gsl_vector* vecbStrain[6];
+ gsl_vector* vecbStress[6];
+ gsl_vector* vecbplStrain;
+ Index i,j;
+
+ // initialize gsl vectors and matrix.
+ matA = gsl_matrix_alloc(4,4); gsl_matrix_set_zero( matA );
+ vecaplStrain = gsl_vector_alloc(4); gsl_vector_set_zero( vecaplStrain );
+ vecbplStrain = gsl_vector_alloc(4); gsl_vector_set_zero( vecbplStrain );
+ for(i=0;i<6;i++) {
+ vecaStrain[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecaStrain[i] );
+ vecaStress[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecaStress[i] );
+ vecbStrain[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecbStrain[i] );
+ vecbStress[i] = gsl_vector_alloc(4); gsl_vector_set_zero( vecbStress[i] );
+ }
+
+ /* For each incident element, find inicident tets. */
+ for( nodeElement_I = 0; nodeElement_I < nodeElementCount; nodeElement_I++ ) {
+ Element_DomainIndex element_dI = context->mesh->nodeElementTbl[node_lI][nodeElement_I];
+
+ if( element_dI < mesh->elementDomainCount ) {
+ Index elementTetra_I;
+ Snac_Element* element = Snac_Element_At( context, element_dI );
+
+ /* Extract the element's node indices. Note that there should always be eight of these. */
+ {
+ Element_GlobalIndex element_gI;
+
+ elements = Memory_Alloc_Array( Node_DomainIndex, nodeElementCount, "SnacRemesher" );
+ element_gI = Mesh_ElementMapDomainToGlobal( mesh, element_dI );
+ nLayout->buildElementNodes( nLayout, element_gI, elements );
+ }
+
+ /* Convert global node indices to domain. */
+ {
+ unsigned eltNode_i;
+
+ for( eltNode_i = 0; eltNode_i < nodeElementCount; eltNode_i++ ) {
+ elements[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, elements[eltNode_i] );
+ }
+ }
+
+ /* For each incident tetrahedron in the incident element,
+ add up contributions to P, A, and b as in Zienkiewicz and Zhu (1992), p. 1336 */
+ for( elementTetra_I = 0; elementTetra_I < Node_Element_Tetrahedra_Count;elementTetra_I++ ) {
+ Tetrahedra_Index tetra_I = NodeToTetra[nodeElement_I][elementTetra_I];
+ Coord tCrds[4];
+ double positionP[4] = {1.0,0.0,0.0,0.0};
+ Index ii,jj;
+
+ /* Extract the tetrahedron's coordinates. */
+ Vector_Set( tCrds[0], mesh->nodeCoord[elements[TetraToNode[tetra_I][0]]] );
+ Vector_Set( tCrds[1], mesh->nodeCoord[elements[TetraToNode[tetra_I][1]]] );
+ Vector_Set( tCrds[2], mesh->nodeCoord[elements[TetraToNode[tetra_I][2]]] );
+ Vector_Set( tCrds[3], mesh->nodeCoord[elements[TetraToNode[tetra_I][3]]] );
+
+ for(ii=1;ii<4;ii++)
+ for(jj=0;jj<4;jj++)
+ positionP[ii] += (0.25f * tCrds[jj][ii-1]);
+
+ for(ii=0;ii<4;ii++) {
+ double tmp;
+ tmp = gsl_vector_get(vecbStrain[0],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][0];
+ gsl_vector_set(vecbStrain[0],ii,tmp);
+ tmp = gsl_vector_get(vecbStrain[1],ii) + positionP[ii]*element->tetra[tetra_I].strain[1][1];
+ gsl_vector_set(vecbStrain[1],ii,tmp);
+ tmp = gsl_vector_get(vecbStrain[2],ii) + positionP[ii]*element->tetra[tetra_I].strain[2][2];
+ gsl_vector_set(vecbStrain[2],ii,tmp);
+ tmp = gsl_vector_get(vecbStrain[3],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][1];
+ gsl_vector_set(vecbStrain[3],ii,tmp);
+ tmp = gsl_vector_get(vecbStrain[4],ii) + positionP[ii]*element->tetra[tetra_I].strain[0][2];
+ gsl_vector_set(vecbStrain[4],ii,tmp);
+ tmp = gsl_vector_get(vecbStrain[5],ii) + positionP[ii]*element->tetra[tetra_I].strain[1][2];
+ gsl_vector_set(vecbStrain[5],ii,tmp);
+
+ tmp = gsl_vector_get(vecbStress[0],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][0];
+ gsl_vector_set(vecbStress[0],ii,tmp);
+ tmp = gsl_vector_get(vecbStress[1],ii) + positionP[ii]*element->tetra[tetra_I].stress[1][1];
+ gsl_vector_set(vecbStress[1],ii,tmp);
+ tmp = gsl_vector_get(vecbStress[2],ii) + positionP[ii]*element->tetra[tetra_I].stress[2][2];
+ gsl_vector_set(vecbStress[2],ii,tmp);
+ tmp = gsl_vector_get(vecbStress[3],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][1];
+ gsl_vector_set(vecbStress[3],ii,tmp);
+ tmp = gsl_vector_get(vecbStress[4],ii) + positionP[ii]*element->tetra[tetra_I].stress[0][2];
+ gsl_vector_set(vecbStress[4],ii,tmp);
+ tmp = gsl_vector_get(vecbStress[5],ii) + positionP[ii]*element->tetra[tetra_I].stress[1][2];
+ gsl_vector_set(vecbStress[5],ii,tmp);
+
+/* tmp = gsl_vector_get(vecbplStrain,i) + positionP[i]*plasticElement->tetra[tetra_I].stress[1][2]; */
+/* gsl_vector_set(vecStress[5],i,tmp); */
+ for(jj=0;jj<4;jj++) {
+ tmp = gsl_matrix_get(matA,ii,jj) + positionP[ii]*positionP[jj];
+ gsl_matrix_set(matA,ii,jj,tmp);
+ }
+ }
+ } // end of incident tets.
+ } // if within my domain
+ } // end of incident elements.
+
+ // compute parameter vectors.
+ {
+ int s;
+ gsl_permutation * p = gsl_permutation_alloc (4);
+
+ gsl_linalg_LU_decomp (matA, p, &s);
+
+ for(i=0;i<6;i++) {
+ gsl_linalg_LU_solve (matA, p, vecbStrain[i], vecaStrain[i]);
+ gsl_linalg_LU_solve (matA, p, vecbStress[i], vecaStress[i]);
+ }
+/* printf ("x = \n"); */
+/* gsl_vector_fprintf (stdout, x, "%g"); */
+ gsl_permutation_free (p);
+ }
+
+ // zero the arrays to store recovered field.
+ // probably not necessary.
+/* for(i=0;i<6;i++) { */
+/* node->strainSPR[i] = 0.0f; */
+/* node->stressSPR[i] = 0.0f; */
+/* } */
+
+ // Recover using the parameter vectors.
+ for(j=0;j<6;j++) {
+ node->strainSPR[j] = gsl_vector_get(vecaStrain[j],0);
+ node->stressSPR[j] = gsl_vector_get(vecaStress[j],0);
+ for(i=0;i<3;i++) {
+ node->strainSPR[j] += gsl_vector_get(vecaStrain[j],i+1)*(*coord)[i];
+ node->stressSPR[j] += gsl_vector_get(vecaStress[j],i+1)*(*coord)[i];
+ }
+ }
+
+ // free gsl vectors and matrix.
+ gsl_matrix_free( matA );
+ gsl_vector_free( vecaplStrain );
+ gsl_vector_free( vecbplStrain );
+ for(i=0;i<6;i++) {
+ gsl_vector_free( vecaStrain[i] );
+ gsl_vector_free( vecaStress[i] );
+ gsl_vector_free( vecbStrain[i] );
+ gsl_vector_free( vecbStress[i] );
+ }
+ /* Free the element node array. */
+ FreeArray( elements );
+ } // end of recovery.
+}
+
+
+
+#if 0
+
+#define DIM 3
+#define NODES_PER_ELEMENT 8
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#define det3_sub( x1, x2, x3 ) ( \
+ (x1)[0] * ( (x2)[1] * (x3)[2] - (x3)[1] * (x2)[2] ) - \
+ (x1)[1] * ( (x2)[0] * (x3)[2] - (x3)[0] * (x2)[2] ) + \
+ (x1)[2] * ( (x2)[0] * (x3)[1] - (x3)[0] * (x2)[1] ) )
+
+#define TetrahedronVolume( x1, x2, x3, x4 ) ( \
+ ( det3_sub( (x2), (x3), (x4) ) - \
+ det3_sub( (x1), (x3), (x4) ) + \
+ det3_sub( (x1), (x2), (x4) ) - \
+ det3_sub( (x1), (x2), (x3) ) \
+ ) / 6.0f )
+
+extern double isLargerThanZero( double, double );
+extern double isLargerThanZero2( double, double, double );
+extern void xyz2tprCoord( Coord, Coord* );
+extern void tpr2xyzCoord( Coord, Coord* );
+extern void xyz2tprVel( Coord, Coord, Coord* );
+extern void tpr2xyzVel( Coord, Coord, Coord* );
+
+/* For a given tetra_I (only interesting in first 5), what is the en_I of a given node of that tetra */
+const int nsub[] = {
+ 0, 2, 3, 7,
+ 0, 1, 2, 5,
+ 4, 7, 5, 0,
+ 5, 7, 6, 2,
+ 5, 7, 2, 0,
+ 3, 7, 4, 6,
+ 4, 0, 3, 1,
+ 6, 2, 1, 3,
+ 1, 5, 6, 4,
+ 1, 6, 3, 4
+};
+
+
+void _SnacRemesher_InterpolateNode(
+ void* _context,
+ Index contribution,
+ double shapeFunction[4],
+ Node_LocalIndex node_lI,
+ Node_LocalIndex fromNode_lI,
+ Partition_Index fromNode_rn_I,
+ Node_ShadowIndex fromNode_sI,
+ Snac_Node* newNode,
+ Snac_Node** shadowNode )
+{
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ context->mesh,
+ SnacRemesher_MeshHandle );
+ Snac_Node* node = (Snac_Node*)ExtensionManager_At( context->mesh->nodeExtensionMgr, newNode, node_lI );
+ Snac_Node* fromNode;
+ Index d;
+ Coord temp,temp1,temp2,newNodeCoordS;
+
+ /* Zero out on first addition */
+ if( contribution == 0 ) {
+ memset( node->velocity, 0, sizeof(double) * DIM );
+ }
+ /* Deference source node (local/shadow) */
+ if( fromNode_lI < context->mesh->nodeLocalCount ) {
+ fromNode = Snac_Node_At( context, fromNode_lI );
+ }
+ else {
+ fromNode = (Snac_Node*)ExtensionManager_At( context->mesh->nodeExtensionMgr, shadowNode[fromNode_rn_I], fromNode_sI );
+ }
+ if(meshExt->meshType == SnacRemesher_Spherical) {
+ xyz2tprVel( meshExt->newNodeCoord[node_lI], fromNode->velocity, &temp1 );
+ for( d = 0; d < DIM; d++ ) {
+ temp2[d] = temp1[d] * shapeFunction[contribution];
+ }
+ xyz2tprCoord( meshExt->newNodeCoord[node_lI], &newNodeCoordS );
+ tpr2xyzVel( newNodeCoordS, temp2, &temp );
+ node->velocity[0] += temp[0];
+ node->velocity[1] += temp[1];
+ node->velocity[2] += temp[2];
+ }
+ else {
+ for( d = 0; d < DIM; d++ ) {
+ node->velocity[d] += fromNode->velocity[d] * shapeFunction[contribution];
+ }
+ }
+}
+
+void _SnacRemesher_InterpolateNodes( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ context->mesh,
+ SnacRemesher_MeshHandle );
+
+ void _SnacRemesher_InterpolateNodes_Cartesian( void* _context );
+ void _SnacRemesher_InterpolateNodes_Spherical( void* _context );
+
+ if(meshExt->meshType == SnacRemesher_Spherical ) {
+ _SnacRemesher_InterpolateNodes_Spherical( context );
+ return;
+ }
+ else {
+ _SnacRemesher_InterpolateNodes_Cartesian( context );
+ return;
+ }
+}
+
+void _SnacRemesher_InterpolateNodes_Cartesian( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ int* ind;
+ Index d;
+ Element_LocalIndex elX,elY,elZ;
+ Element_LocalIndex nodeX,nodeY,nodeZ;
+ Element_NodeIndex elementNodeCount;
+ double xc[DIM*NODES_PER_ELEMENT];
+ PartitionIndex rn_I;
+ Node_LocalIndex node_lI,node_lN;
+ unsigned int All_passed;
+ double TOL;
+ int count;
+ const int shadowDepth = ( decomp->shadowDepth > 3) ? decomp->shadowDepth : 3;
+ const int numSearchElement = 2*shadowDepth-1;
+ const int numSearchDepth = shadowDepth-1;
+ const Element_LocalIndex nElementX=decomp->elementLocal3DCounts[decomp->rank][0];
+ const Element_LocalIndex nElementY=decomp->elementLocal3DCounts[decomp->rank][1];
+ const Element_LocalIndex nElementZ=decomp->elementLocal3DCounts[decomp->rank][2];
+ const Node_LocalIndex nNodeX=decomp->nodeLocal3DCounts[decomp->rank][0];
+ const Node_LocalIndex nNodeY=decomp->nodeLocal3DCounts[decomp->rank][1];
+ const Node_LocalIndex nNodeZ=decomp->nodeLocal3DCounts[decomp->rank][2];
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ ind = (int*)malloc( sizeof( int ) * meshExt->nodeLocalCount );
+ memset( ind, 0, sizeof( int ) * meshExt->nodeLocalCount );
+
+ /* for all nodes, interpolate velocity; loop over local elements */
+ All_passed = 0;
+ TOL= 0.0f;
+ while(!All_passed) {
+ for(nodeZ=0; nodeZ < nNodeZ; nodeZ++)
+ for(nodeY=0; nodeY < nNodeY; nodeY++)
+ for(nodeX=0; nodeX < nNodeX; nodeX++) {
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Element_LocalIndex searchElement_lI,searchElement_lJ,searchElement_lK;
+ Element_LocalIndex element_lN;
+
+ int found;
+ Tetrahedra_Index tetra_I;
+ Coord newNodeCoord;
+
+ /* Ensure we haven't already done this node */
+ node_lI = nodeX + nodeY*nNodeX + nodeZ*nNodeX*nNodeY;
+ if( ind[node_lI] ) {
+ continue;
+ }
+ elX = (nodeX <= 1)? 0 : (nodeX-1);
+ elY = (nodeY <= 1)? 0 : (nodeY-1);
+ elZ = (nodeZ <= 1)? 0 : (nodeZ-1);
+
+ newNodeCoord[0] = meshExt->newNodeCoord[node_lI][0];
+ newNodeCoord[1] = meshExt->newNodeCoord[node_lI][1];
+ newNodeCoord[2] = meshExt->newNodeCoord[node_lI][2];
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (elZ+searchElement_lK-numSearchDepth) < 0 || (elZ+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lJ=0;searchElement_lJ<numSearchElement;searchElement_lJ++) {
+ if( (elY+searchElement_lJ-numSearchDepth) < 0 || (elY+searchElement_lJ-numSearchDepth) >= nElementY )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (elX+searchElement_lI-numSearchDepth) < 0 || (elX+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (elX+searchElement_lI-numSearchDepth) + (elY+searchElement_lJ-numSearchDepth)*nElementX
+ + (elZ+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ if( ind[node_lI] ) {
+ break;
+ }
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++) {
+ node_lN = elementNodeTbl[element_lN][en_N];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ //xc[en_N*DIM+2] = meshExt->initialNodeCoord[elementNodeTbl[element_lN][en_N]][2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_N*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_N*DIM+d] );
+ }
+ }
+
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( newNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoord[1] < elembbox[0][1]-0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoord[1] > elembbox[1][1]+0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ newNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) ) {
+ continue;
+ }
+
+ /* loop over 10 sub tets in a brick element, work out the tetra it is in, and then interpolate */
+ found = 0;
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count && !found; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double x4[DIM];
+ double dett;
+ double det[4];
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nsub[tetra_I*4]*DIM+d];
+ x2[d] = xc[nsub[tetra_I*4+1]*DIM+d];
+ x3[d] = xc[nsub[tetra_I*4+2]*DIM+d];
+ x4[d] = xc[nsub[tetra_I*4+3]*DIM+d];
+ }
+
+ dett = TetrahedronVolume( x1, x2, x3, x4 );
+ det[0] = TetrahedronVolume( x2, x4, x3, newNodeCoord );
+ det[1] = TetrahedronVolume( x3, x4, x1, newNodeCoord );
+ det[2] = TetrahedronVolume( x1, x4, x2, newNodeCoord );
+ det[3] = TetrahedronVolume( x1, x2, x3, newNodeCoord );
+
+ dett = isLargerThanZero( dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ assert( dett != 0.0 );
+ if( dett < 0 ) {
+ printf( "Determinant evaluation is wrong node=%d\t xt[0]=%g \t xt[1]=%g \t xt[t]=%g\n",
+ en_N,
+ newNodeCoord[0],
+ newNodeCoord[1],
+ newNodeCoord[2]);
+ continue;
+ }
+
+ /* found if all det are greater than zero */
+ if ( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f && det[3] >= 0.0f ) {
+ found = 1;
+ }
+ //fprintf(stderr,"%s: node_lI=%d element_lN=%d ind=%d foun=%d newCoord=%e %e %e\n\tdett=%e %e %e %e\n",__func__,node_lI,element_lN,ind[node_lI],found,newNodeCoord[0],newNodeCoord[1],newNodeCoord[2],det[0],det[1],det[2],dett);
+
+ if( found ) {
+ double shape[4];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[node_lI] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+
+ if( elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]] >
+ context->mesh->nodeLocalCount ) {
+ int i;
+
+ printf( "element_lN: %u, nsub[tetra_I*4+tNode_I]: %u\n",
+ element_lN,
+ nsub[tetra_I*4+tNode_I] );
+ printf( "elementNodeTbl: %p, { ",
+ elementNodeTbl );
+ for( i = 0; i < 8; i++ ) {
+ printf( "%u, ",
+ elementNodeTbl[element_lN][i] );
+ }
+ printf( "\n" );
+ assert(
+ elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]] >
+ context->mesh->nodeLocalCount );
+ }
+
+ SnacRemesher_InterpolateNode(
+ context,
+ contextExt,
+ tNode_I,
+ shape,
+ node_lI,
+ elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]],
+ 0,
+ 0,
+ meshExt->newNode,
+ 0 );
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+
+ if(ind[node_lI] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ Index node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ unsigned int found = 0;
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] = context->mesh->nodeGlobalCount + node_sI;
+ found = 1;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ node_lN = shadowElementNodesN[en_N];
+ if( node_lN < context->mesh->nodeDomainCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ }
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xc[en_N*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xc[en_N*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( newNodeCoord[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoord[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoord[1] < elembbox[0][1]-0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoord[1] > elembbox[1][1]+0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoord[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ newNodeCoord[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ //assert(0);
+ continue;
+ }
+
+ /* loop over 10 sub tets in a brick element, work out the tetra it is in, and then interpolate */
+ found = 0;
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count && !found; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double x4[DIM];
+ double dett;
+ double det[4];
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xc[nsub[tetra_I*4]*DIM+d];
+ x2[d] = xc[nsub[tetra_I*4+1]*DIM+d];
+ x3[d] = xc[nsub[tetra_I*4+2]*DIM+d];
+ x4[d] = xc[nsub[tetra_I*4+3]*DIM+d];
+ }
+ dett = TetrahedronVolume( x1, x2, x3, x4 );
+ det[0] = TetrahedronVolume( x2, x4, x3, newNodeCoord );
+ det[1] = TetrahedronVolume( x3, x4, x1, newNodeCoord );
+ det[2] = TetrahedronVolume( x1, x4, x2, newNodeCoord );
+ det[3] = TetrahedronVolume( x1, x2, x3, newNodeCoord );
+
+ dett = isLargerThanZero( dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ Journal_Firewall( dett != 0.0, context->snacError, "node_lI=%d element_sN=%d me=%d TOL=%e newCoord=%e %e %e\nx1(%d)= %e %e %e\nx2(%d)= %e %e %e \nx3(%d)= %e %e %e\nx4(%d)= %e %e %e\ndett=%e (%e %e %e %e)\n", node_lI,element_sN,context->rank,TOL, newNodeCoord[0],newNodeCoord[1],newNodeCoord[2],nsub[tetra_I*4],x1[0],x1[1],x1[2],nsub[tetra_I*4+1],x2[0],x2[1],x2[2],nsub[tetra_I*4+2],x3[0],x3[1],x3[2],nsub[tetra_I*4+3],x4[0],x4[1],x4[2],dett,det[0],det[1],det[2],det[3]);
+
+ if( dett < 0 ) {
+ continue;
+ }
+
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f && det[3] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[4];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[node_lI] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ SnacRemesher_InterpolateNode(
+ context,
+ contextExt,
+ tNode_I,
+ shape,
+ node_lI,
+ shadowElementNodesN[nsub[tetra_I*4+tNode_I]],
+ rn_I,
+ shadowElementNodesN[nsub[tetra_I*4+tNode_I]] -
+ context->mesh->nodeGlobalCount,
+ meshExt->newNode,
+ meshExt->shadowNodeRemote );
+ }
+ break;
+ }
+ }
+ if( shadowElementNodesN )
+ free( shadowElementNodesN );
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lI = 0; node_lI < meshExt->nodeLocalCount; node_lI++ ) {
+ //fprintf(stderr,"Interpolating Nodal values rank=%d Node #%d ind=%d\n",context->rank,node_lI,ind[node_lI]);
+ if( ind[node_lI] == 0 ) {
+ Journal_DPrintf( context->debug,
+ " timeStep=%d rank=%d Node #%d cannot find tetra, New coord=%e %e %e coord=%e %e %e diff=%e %e %e\n",
+ context->timeStep,context->rank,node_lI,
+ meshExt->newNodeCoord[node_lI][0],meshExt->newNodeCoord[node_lI][1],meshExt->newNodeCoord[node_lI][2],
+ mesh->nodeCoord[node_lI][0],mesh->nodeCoord[node_lI][1],mesh->nodeCoord[node_lI][2],
+ meshExt->newNodeCoord[node_lI][0]-mesh->nodeCoord[node_lI][0],
+ meshExt->newNodeCoord[node_lI][1]-mesh->nodeCoord[node_lI][1],
+ meshExt->newNodeCoord[node_lI][2]-mesh->nodeCoord[node_lI][2]
+ );
+
+ All_passed = 0;
+ count++;
+ //fprintf(stderr,"me=%d failed node=%d\n",context->rank,node_lI);
+ }
+ }
+ if(TOL==0.0)TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_DPrintf( context->debug," In: %s,rank=%d Increased tolerance: %e, the number of failed nodde: %d\n", __func__, context->rank, TOL,count);
+ Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s,rank=%d Increased tolerance: %e, the number of failed nodde: %d\n", __func__, context->rank, TOL,count);
+ }
+ free( ind );
+}
+
+
+
+void _SnacRemesher_InterpolateNodes_Spherical( void* _context ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ SnacRemesher_Context* contextExt = ExtensionManager_Get(
+ context->extensionMgr,
+ context,
+ SnacRemesher_ContextHandle );
+ Mesh* mesh = context->mesh;
+ HexaMD* decomp = (HexaMD*)mesh->layout->decomp;
+ SnacRemesher_Mesh* meshExt = ExtensionManager_Get(
+ context->meshExtensionMgr,
+ mesh,
+ SnacRemesher_MeshHandle );
+ int* ind;
+ Index d;
+ Element_LocalIndex elX,elY,elZ;
+ Element_LocalIndex nodeX,nodeY,nodeZ;
+ Element_NodeIndex elementNodeCount;
+ double xc[DIM*NODES_PER_ELEMENT];
+ double xcs[DIM*NODES_PER_ELEMENT];
+ PartitionIndex rn_I;
+ Node_LocalIndex node_lI,node_lN;
+ unsigned int All_passed;
+ double TOL;
+ int count;
+ const int shadowDepth = ( decomp->shadowDepth > 3) ? decomp->shadowDepth : 3;
+ const int numSearchElement = 2*shadowDepth-1;
+ const int numSearchDepth = shadowDepth-1;
+ const Element_LocalIndex nElementX=decomp->elementLocal3DCounts[decomp->rank][0];
+ const Element_LocalIndex nElementY=decomp->elementLocal3DCounts[decomp->rank][1];
+ const Element_LocalIndex nElementZ=decomp->elementLocal3DCounts[decomp->rank][2];
+ const Node_LocalIndex nNodeX=decomp->nodeLocal3DCounts[decomp->rank][0];
+ const Node_LocalIndex nNodeY=decomp->nodeLocal3DCounts[decomp->rank][1];
+ const Node_LocalIndex nNodeZ=decomp->nodeLocal3DCounts[decomp->rank][2];
+
+ Journal_DPrintf( context->debug, "In: %s\n", __func__ );
+
+ ind = (int*)malloc( sizeof( int ) * meshExt->nodeLocalCount );
+ memset( ind, 0, sizeof( int ) * meshExt->nodeLocalCount );
+
+ /* for all nodes, interpolate velocity; loop over local elements */
+ All_passed = 0;
+ TOL= 0.0f;
+ while(!All_passed) {
+ for(nodeZ=0; nodeZ < nNodeZ; nodeZ++)
+ for(nodeY=0; nodeY < nNodeY; nodeY++)
+ for(nodeX=0; nodeX < nNodeX; nodeX++) {
+ Element_NodeIndex en_N;
+ double elembbox[2][DIM];
+ Node_LocalIndex** elementNodeTbl = context->mesh->elementNodeTbl;
+ Coord temp1,temp2;
+ Element_LocalIndex searchElement_lI,searchElement_lJ,searchElement_lK;
+ Element_LocalIndex element_lN;
+
+ int found;
+ Tetrahedra_Index tetra_I;
+ Coord newNodeCoord;
+ Coord newNodeCoordS;
+
+ /* Ensure we haven't already done this node */
+ node_lI = nodeX + nodeY*nNodeX + nodeZ*nNodeX*nNodeY;
+ if( ind[node_lI] ) {
+ continue;
+ }
+ elX = (nodeX <= 1)? 0 : (nodeX-1);
+ elY = (nodeY <= 1)? 0 : (nodeY-1);
+ elZ = (nodeZ <= 1)? 0 : (nodeZ-1);
+
+ /* otherwise, try to interpolate old mesh's values for the new coordinates */
+ newNodeCoord[0] = meshExt->newNodeCoord[node_lI][0];
+ newNodeCoord[1] = meshExt->newNodeCoord[node_lI][1];
+ newNodeCoord[2] = meshExt->newNodeCoord[node_lI][2];
+ xyz2tprCoord( newNodeCoord, &newNodeCoordS );
+ newNodeCoordS[1] /= 6371000.0;
+
+ for(searchElement_lK=0;searchElement_lK<numSearchElement;searchElement_lK++) {
+ if( (elZ+searchElement_lK-numSearchDepth) < 0 || (elZ+searchElement_lK-numSearchDepth) >= nElementZ )
+ continue;
+ for(searchElement_lJ=0;searchElement_lJ<numSearchElement;searchElement_lJ++) {
+ if( (elY+searchElement_lJ-numSearchDepth) < 0 || (elY+searchElement_lJ-numSearchDepth) >= nElementY )
+ continue;
+ for(searchElement_lI=0;searchElement_lI<numSearchElement;searchElement_lI++) {
+ if( (elX+searchElement_lI-numSearchDepth) < 0 || (elX+searchElement_lI-numSearchDepth) >= nElementX )
+ continue;
+ element_lN = (elX+searchElement_lI-numSearchDepth) + (elY+searchElement_lJ-numSearchDepth)*nElementX
+ + (elZ+searchElement_lK-numSearchDepth)*nElementY*nElementX;
+
+ if( ind[node_lI] ) {
+ break;
+ }
+
+ elementNodeCount = context->mesh->elementNodeCountTbl[element_lN];
+ if( elementNodeCount != (unsigned)NODES_PER_ELEMENT ) {
+ printf( "elementNodeCount != NODES_PER_ELEMENT element_lN = %d", element_lN );
+ assert( 0 );
+ }
+
+ /* create a local copy of the veocity and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++) {
+
+ node_lN = elementNodeTbl[element_lN][en_N];
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_N*DIM+0];
+ temp1[1] = xc[en_N*DIM+1];
+ temp1[2] = xc[en_N*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_N*DIM+0] = temp2[0];
+ xcs[en_N*DIM+1] = temp2[1]/6371000.0;
+ xcs[en_N*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; d++ ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_N*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_N*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if(
+ newNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoordS[1] < elembbox[0][1]-0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoordS[1] > elembbox[1][1]+0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ newNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) ) {
+ continue;
+ }
+ /* if the current coord is very close to the initial ones, just copy those initial values rather than bother to compute determinents and add error */
+ if( ( meshExt->newNodeCoord[node_lI][0] >= mesh->nodeCoord[node_lI][0] - TOL*(elembbox[1][0]-elembbox[0][0]) && meshExt->newNodeCoord[node_lI][0] <= mesh->nodeCoord[node_lI][0] + TOL*(elembbox[1][0]-elembbox[0][0]) ) &&
+ ( meshExt->newNodeCoord[node_lI][1] >= mesh->nodeCoord[node_lI][1] - TOL*(elembbox[1][1]-elembbox[0][1]) && meshExt->newNodeCoord[node_lI][1] <= mesh->nodeCoord[node_lI][1] + TOL*(elembbox[1][1]-elembbox[0][1]) ) &&
+ ( meshExt->newNodeCoord[node_lI][2] >= mesh->nodeCoord[node_lI][2] - TOL*(elembbox[1][2]-elembbox[0][2]) && meshExt->newNodeCoord[node_lI][2] <= mesh->nodeCoord[node_lI][2] + TOL*(elembbox[1][2]-elembbox[0][2]) ) ) {
+ ind[node_lI] = 1;
+ continue;
+ }
+
+ /* loop over 10 sub tets in a brick element, work out the tetra it is in, and then interpolate */
+ found = 0;
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count && !found; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double x4[DIM];
+ double dett;
+ double det[4];
+
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nsub[tetra_I*4]*DIM+d];
+ x2[d] = xcs[nsub[tetra_I*4+1]*DIM+d];
+ x3[d] = xcs[nsub[tetra_I*4+2]*DIM+d];
+ x4[d] = xcs[nsub[tetra_I*4+3]*DIM+d];
+ }
+
+ dett = TetrahedronVolume( x1, x2, x3, x4 );
+ det[0] = TetrahedronVolume( x2, x4, x3, newNodeCoordS );
+ det[1] = TetrahedronVolume( x3, x4, x1, newNodeCoordS );
+ det[2] = TetrahedronVolume( x1, x4, x2, newNodeCoordS );
+ det[3] = TetrahedronVolume( x1, x2, x3, newNodeCoordS );
+
+ dett = isLargerThanZero2( dett, dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ assert( dett != 0.0 );
+ if( dett <= 0 ) {
+ continue;
+ }
+
+ /* found if all det are greater than zero */
+ if ( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f && det[3] >= 0.0f ) {
+ found = 1;
+ }
+
+ if( found ) {
+ double shape[4];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[node_lI] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+
+ if( elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]] >
+ context->mesh->nodeLocalCount ) {
+ int i;
+
+ printf( "element_lI: %u, nsub[tetra_I*4+tNode_I]: %u\n",
+ element_lN,
+ nsub[tetra_I*4+tNode_I] );
+ printf( "elementNodeTbl: %p, { ",
+ elementNodeTbl );
+ for( i = 0; i < 8; i++ ) {
+ printf( "%u, ",
+ elementNodeTbl[element_lN][i] );
+ }
+ printf( "\n" );
+ assert(
+ elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]] >
+ context->mesh->nodeLocalCount );
+ }
+
+ SnacRemesher_InterpolateNode(
+ context,
+ contextExt,
+ tNode_I,
+ shape,
+ node_lI,
+ elementNodeTbl[element_lN][nsub[tetra_I*4+tNode_I]],
+ 0,
+ 0,
+ meshExt->newNode,
+ 0 );
+ }
+ break;
+ }
+#if 0
+ if(context->rank==0 && node_lI==32)
+ fprintf(stderr,"Found? %d TOL=%e timeStep=%d me=%d element_lI=%d node_lI=%d tetra_I=%d\nxc=(%e %e %e) (%e %e %e) (%e %e %e) (%e %e %e)\nnewX=%e %e %e bbox=(%e %e) (%e %e) (%e %e)\ndett=%e %e %e %e %e\n\n",
+ found,TOL,context->timeStep,context->rank,element_lN,node_lI,tetra_I,
+ x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],x3[0],x3[1],x3[2],x4[0],x4[1],x4[2],
+ newNodeCoordS[0],newNodeCoordS[1],newNodeCoordS[2],
+ elembbox[0][0],elembbox[1][0],elembbox[0][1],elembbox[1][1],elembbox[0][2],elembbox[1][2],
+ det[0],det[1],det[2],det[3],dett);
+#endif
+ }
+ }
+ }
+ }
+ /*
+ ** Loop over shadow elements
+ */
+ for( rn_I = 0; rn_I < meshExt->neighbourRankCount; rn_I++ ) {
+ Element_ShadowIndex element_sN;
+
+ /* Loop over all the shadow elements to find one including node_lI */
+ for( element_sN = 0; element_sN < meshExt->shadowElementRemoteCount[rn_I]; element_sN++ ) {
+ Element_GlobalIndex gElement_N = meshExt->shadowElementRemoteArray[rn_I][element_sN];
+ Node_Index* shadowElementNodesN = (Node_Index*)malloc( sizeof(Node_Index) * NODES_PER_ELEMENT );
+ Index en_N;
+ double elembbox[2][DIM];
+ Node_GlobalIndex elementNodeN[8];
+
+ if(ind[node_lI] == 1)
+ break;
+
+ /* Figure out node index */
+ _HexaEL_BuildCornerIndices( context->mesh->layout->elementLayout, gElement_N, elementNodeN );
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ Node_GlobalIndex node_gN = elementNodeN[en_N];
+ Index node_lN = Mesh_NodeMapGlobalToLocal( context->mesh, node_gN );
+ unsigned int found = 0;
+ if( node_lN < meshExt->nodeLocalCount ) {
+ shadowElementNodesN[en_N] = node_lN;
+ found = 1;
+ elementNodeN[en_N] = node_lN;
+ }
+ else {
+ Node_ShadowIndex node_sI;
+ for( node_sI = 0; node_sI < meshExt->shadowNodeRemoteCount[rn_I]; node_sI++ ) {
+ if( node_gN == meshExt->shadowNodeRemoteArray[rn_I][node_sI] ) {
+ shadowElementNodesN[en_N] = context->mesh->nodeGlobalCount + node_sI;
+ found = 1;
+ }
+ }
+ }
+ assert( found ); /* we expected this to be a shadow node, but wasn't in list! */
+ }
+
+ /* create a local copy of the temp, vel, and coords for each of the element's nodes of the old mesh */
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ /* copying nodal field values and nodal coordinates of the old mesh for each hex element into local
+ array */
+ node_lN = shadowElementNodesN[en_N];
+ if( node_lN < context->mesh->nodeLocalCount ) {
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = Mesh_CoordAt( context->mesh, node_lN )[d];
+ }
+ }
+ else {
+ node_lN -= context->mesh->nodeGlobalCount;
+ for( d = 0; d < DIM; d++ ) {
+ xc[en_N*DIM+d] = meshExt->shadowNodeRemoteCoord[rn_I][node_lN][d];
+ }
+ }
+ // (0,1,2) <=> (x,y,z) <=> (fi,r,theta)
+ temp1[0] = xc[en_N*DIM+0];
+ temp1[1] = xc[en_N*DIM+1];
+ temp1[2] = xc[en_N*DIM+2];
+ xyz2tprCoord( temp1, &temp2 );
+ xcs[en_N*DIM+0] = temp2[0];
+ xcs[en_N*DIM+1] = temp2[1]/6371000.0;
+ xcs[en_N*DIM+2] = temp2[2];
+ }
+
+ /* Calculate element's bounding box */
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = DBL_MAX;
+ elembbox[1][d] = DBL_MIN;
+ }
+ for( en_N = 0; en_N < NODES_PER_ELEMENT; en_N++ ) {
+ for( d = 0; d < DIM; ++d ) {
+ elembbox[0][d] = MIN( elembbox[0][d], xcs[en_N*DIM+d] );
+ elembbox[1][d] = MAX( elembbox[1][d], xcs[en_N*DIM+d] );
+ }
+ }
+ /* If new mesh's current node is outside the bounding box, next loop */
+ if( newNodeCoordS[0] < elembbox[0][0]-0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoordS[0] > elembbox[1][0]+0.5f*(elembbox[1][0]-elembbox[0][0]) ||
+ newNodeCoordS[1] < elembbox[0][1]-0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoordS[1] > elembbox[1][1]+0.5f*(elembbox[1][1]-elembbox[0][1]) ||
+ newNodeCoordS[2] < elembbox[0][2]-0.5f*(elembbox[1][2]-elembbox[0][2]) ||
+ newNodeCoordS[2] > elembbox[1][2]+0.5f*(elembbox[1][2]-elembbox[0][2]) )
+ {
+ continue;
+ }
+
+ /* loop over 10 sub tets in a brick element, work out the tetra it is in, and then interpolate */
+ found = 0;
+ for( tetra_I = 0; tetra_I < Tetrahedra_Count && !found; tetra_I++ ) {
+ double x1[DIM];
+ double x2[DIM];
+ double x3[DIM];
+ double x4[DIM];
+ double dett;
+ double det[4];
+
+ for( d = 0; d < DIM; d++ ) {
+ x1[d] = xcs[nsub[tetra_I*4]*DIM+d];
+ x2[d] = xcs[nsub[tetra_I*4+1]*DIM+d];
+ x3[d] = xcs[nsub[tetra_I*4+2]*DIM+d];
+ x4[d] = xcs[nsub[tetra_I*4+3]*DIM+d];
+ }
+
+ dett = TetrahedronVolume( x1, x2, x3, x4 );
+ det[0] = TetrahedronVolume( x2, x4, x3, newNodeCoordS );
+ det[1] = TetrahedronVolume( x3, x4, x1, newNodeCoordS );
+ det[2] = TetrahedronVolume( x1, x4, x2, newNodeCoordS );
+ det[3] = TetrahedronVolume( x1, x2, x3, newNodeCoordS );
+
+ dett = isLargerThanZero2( dett, dett, TOL );
+ det[0] = isLargerThanZero2( det[0], dett, TOL );
+ det[1] = isLargerThanZero2( det[1], dett, TOL );
+ det[2] = isLargerThanZero2( det[2], dett, TOL );
+ det[3] = isLargerThanZero2( det[3], dett, TOL );
+ dett = det[0] + det[1] + det[2] + det[3];
+
+ Journal_Firewall( dett != 0.0, context->snacError, "node_lI=%d element_sN=%d me=%d TOL=%e newCoord=%e %e %e\nx1(%d)= %e %e %e\nx2(%d)= %e %e %e \nx3(%d)= %e %e %e\nx4(%d)= %e %e %e\ndett=%e (%e %e %e %e)\n", node_lI,element_sN,context->rank,TOL, newNodeCoordS[0],newNodeCoordS[1],newNodeCoordS[2],nsub[tetra_I*4],x1[0],x1[1],x1[2],nsub[tetra_I*4+1],x2[0],x2[1],x2[2],nsub[tetra_I*4+2],x3[0],x3[1],x3[2],nsub[tetra_I*4+3],x4[0],x4[1],x4[2],dett,det[0],det[1],det[2],det[3]);
+ if( dett < 0 ) {
+ continue;
+ }
+
+ /* found if all det are greater than zero */
+ if( det[0] >= 0.0f && det[1] >= 0.0f && det[2] >= 0.0f && det[3] >= 0.0f ) {
+ found = 1;
+ }
+ if( found ) {
+ double shape[4];
+ Index tNode_I;
+
+ /* mark, such that we dont do it again */
+ ind[node_lI] = 1;
+
+ /* Calculate the shape funcs */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ shape[tNode_I] = det[tNode_I] / dett;
+ }
+
+ /* Assign proper values of velocities and temperatures from old mesh to new mesh */
+ for( tNode_I = 0; tNode_I < 4; tNode_I++ ) {
+ SnacRemesher_InterpolateNode(
+ context,
+ contextExt,
+ tNode_I,
+ shape,
+ node_lI,
+ shadowElementNodesN[nsub[tetra_I*4+tNode_I]],
+ rn_I,
+ shadowElementNodesN[nsub[tetra_I*4+tNode_I]] -
+ context->mesh->nodeGlobalCount,
+ meshExt->newNode,
+ meshExt->shadowNodeRemote);
+ }
+ break;
+ }
+ }
+ if( shadowElementNodesN )
+ free( shadowElementNodesN );
+ }
+ }
+ }
+ All_passed = 1;
+ count = 0;
+ for( node_lI = 0; node_lI < meshExt->nodeLocalCount; node_lI++ )
+ {
+ if( ind[node_lI] == 0 ) {
+ All_passed = 0;
+ count++;
+ }
+ }
+ if(TOL==0.0)TOL = 1.0e-10;
+ else TOL *= 10.0;
+ Journal_DPrintf( context->debug," In: %s,rank=%d Increased tolerance: %e, the number of failed nodde: %d\n", __func__, context->rank, TOL,count);
+ //Journal_Firewall( TOL <= 1.0e-03, context->snacError," In: %s,rank=%d Increased tolerance: %e, the number of failed nodde: %d\n", __func__, context->rank, TOL,count);
+ }
+
+ free( ind );
+
+}
+
+#endif
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesher.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesher.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Remesher.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,54 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Remesher.h 3095 2005-07-13 09:50:46Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_h__
+#define __SnacRemesher_h__
+
+ #include "types.h"
+ #include "Utils.h"
+ #include "Context.h"
+ #include "Register.h"
+ #include "ConstructExtensions.h"
+ #include "Build.h"
+ #include "InitialConditions.h"
+ #include "TestCondFunc.h"
+ #include "Remesh.h"
+ #include "DeleteExtensions.h"
+
+#endif /* __SnacRemesher_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,112 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: TestCondFunc.c 1792 2004-07-30 05:42:39Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+#include "Snac/Snac.h"
+#include "types.h"
+#include "Register.h"
+#include <stdio.h>
+#include <string.h>
+
+#include <math.h>
+#ifndef PI
+ #ifndef M_PIl
+ #ifndef M_PI
+ #define PI 3.1415927
+ #else
+ #define PI M_PI
+ #endif
+ #else
+ #define PI M_PIl
+ #endif
+#endif
+
+static double Bell( double x ) {
+ return exp( -((x) * (x)) * 10.0f );
+}
+
+
+void _SnacRemesher_TestCondFunc( Index node_dI, Variable_Index var_I, void* _context, void* result ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ MeshLayout* meshLayout = (MeshLayout*)context->meshLayout;
+ HexaMD* decomp = (HexaMD*)meshLayout->decomp;
+
+ double* velComponent = (double*)result;
+ IJK ijk;
+ double x;
+ Node_GlobalIndex node_gI = _MeshDecomp_Node_LocalToGlobal1D( decomp, node_dI );
+
+ RegularMeshUtils_Node_1DTo3D( decomp, node_gI, &ijk[0], &ijk[1], &ijk[2] );
+ x = 1.0f / decomp->nodeGlobal3DCounts[0] * ijk[0] - 0.5;
+ (*velComponent) = Bell( x ) * 5e-7;
+}
+
+void _SnacRemesher_XFunc( Index node_dI, Variable_Index var_I, void* _context, void* result ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ MeshLayout* meshLayout = (MeshLayout*)context->meshLayout;
+ HexaMD* decomp = (HexaMD*)meshLayout->decomp;
+
+ double* velComponent = (double*)result;
+ IJK ijk;
+ const Node_GlobalIndex midI = (decomp->nodeGlobal3DCounts[0] + 1) / 2;
+ Node_GlobalIndex node_gI = _MeshDecomp_Node_LocalToGlobal1D( decomp, node_dI );
+
+ RegularMeshUtils_Node_1DTo3D( decomp, node_gI, &ijk[0], &ijk[1], &ijk[2] );
+ if( ijk[0] < (midI-1) ) {
+ (*velComponent) += 1e-8;
+ }
+ else if( ijk[0] > (midI-1) ) {
+ (*velComponent) -= 1e-7;
+ }
+ /* else: leave centre to be free */
+}
+
+void _SnacRemesher_YFunc( Index node_dI, Variable_Index var_I, void* _context, void* result ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ MeshLayout* meshLayout = (MeshLayout*)context->meshLayout;
+ HexaMD* decomp = (HexaMD*)meshLayout->decomp;
+
+ double* velComponent = (double*)result;
+ IJK ijk;
+ const Node_GlobalIndex midI = (decomp->nodeGlobal3DCounts[0] + 1) / 2;
+ Node_GlobalIndex node_gI = _MeshDecomp_Node_LocalToGlobal1D( decomp, node_dI );
+
+ RegularMeshUtils_Node_1DTo3D( decomp, node_gI, &ijk[0], &ijk[1], &ijk[2] );
+ if( ijk[0] < (midI-1) ) {
+ (*velComponent) += 5e-8;
+ }
+ else if( ijk[0] > (midI-1) ) {
+ (*velComponent) -= 1e-8;
+ }
+ /* else: leave centre to be free */
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/TestCondFunc.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,48 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** Role:
+** Handles the temperature initial and boundary conditions
+**
+** Assumptions:
+** None as yet.
+**
+** Comments:
+** None as yet.
+**
+** $Id: TestCondFunc.h 1506 2004-06-02 18:55:34Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_TestCondFunc_h__
+#define __SnacRemesher_TestCondFunc_h__
+
+ void _SnacRemesher_TestCondFunc( Index node_dI, Variable_Index var_I, void* _context, void* result );
+ void _SnacRemesher_XFunc( Index node_dI, Variable_Index var_I, void* _context, void* result );
+ void _SnacRemesher_YFunc( Index node_dI, Variable_Index var_I, void* _context, void* result );
+
+#endif /* __SnacRemesher_TestCondFunc_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.c
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.c (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.c 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,250 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+** $Id: Utils.c 2749 2005-03-06 06:43:47Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <mpi.h>
+#include <string.h>
+
+#include <StGermain/StGermain.h>
+#include <StGermain/FD/FD.h>
+
+#include "Snac/Snac.h"
+#include "types.h"
+#include "EntryPoint.h"
+#include "Mesh.h"
+#include "Context.h"
+#include "Remesh.h"
+#include "Register.h"
+
+
+Node_DomainIndex findClosestNode( void* _context, Coord point, Node_LocalIndex refNodeInd ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ Topology* nodeTopo = mesh->layout->nodeLayout->topology;
+ Node_DomainIndex curNode = refNodeInd;
+ Bool done = False;
+
+
+ /*
+ ** Search through the mesh's old coordinates to find the closest node to the new node 'newNode'.
+ */
+
+ do {
+ unsigned nNbrs;
+ Node_DomainIndex* nbrs;
+ Coord tmp;
+ double minDist;
+ Node_DomainIndex minNode;
+ unsigned nbr_i;
+
+ /* Collect the neighbours of the current node. */
+ {
+ Node_GlobalIndex gNodeInd;
+
+ gNodeInd = Mesh_NodeMapDomainToGlobal( mesh, curNode );
+ nNbrs = Topology_NeighbourCount( nodeTopo, gNodeInd );
+ if( nNbrs ) {
+ nbrs = Memory_Alloc_Array( Node_DomainIndex, nNbrs, "SnacRemesher" );
+#if 0
+ Topology_BuildNeighbours( nodeTopo, curNode, nbrs );
+#endif
+ }
+ else {
+ nbrs = NULL;
+ }
+ }
+
+ /* Convert neighbours to domain indices. */
+ for( nbr_i = 0; nbr_i < nNbrs; nbr_i++ ) {
+#if 0
+ nbrs[nbr_i] = Mesh_NodeMapGlobalToDomain( mesh, nbrs[nbr_i] );
+#endif
+ nbrs[nbr_i] = mesh->nodeNeighbourTbl[curNode][nbr_i];
+ }
+
+ /* Get the distance to the current node. */
+ Vector_Sub( tmp, point, mesh->nodeCoord[curNode] );
+ minDist = Vector_Mag( tmp );
+ minNode = curNode;
+
+ /* Loop over neighbours to find the closest node. */
+ for( nbr_i = 0; nbr_i < nNbrs; nbr_i++ ) {
+ double dist;
+
+ if( nbrs[nbr_i] >= mesh->nodeDomainCount ) {
+ continue;
+ }
+
+ Vector_Sub( tmp, point, mesh->nodeCoord[nbrs[nbr_i]] );
+ dist = Vector_Mag( tmp );
+
+ if( dist < minDist ) {
+ minDist = dist;
+ minNode = nbrs[nbr_i];
+ }
+ }
+
+ /* Have we found the closest node? */
+ if( minNode == curNode ) {
+ done = True;
+ }
+ else {
+ curNode = minNode;
+ }
+
+ /* Free the neighbour array. */
+ FreeArray( nbrs );
+ }
+ while( !done );
+
+ return curNode;
+}
+
+
+Node_DomainIndex findClosestNodeInElement( void* _context, Coord point, unsigned nEltNodes, Node_DomainIndex *eltNodes ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ /* Bool done = False; */
+ unsigned eltNode_i;
+ Coord tmp;
+ double minDist = 1.0e+32;
+ Node_DomainIndex minNode = 0;
+
+ /*
+ ** Search through the mesh's old coordinates to find the closest node to the new node 'newNode'.
+ */
+
+ /* Get the distance from the current new node to the element nodes in the old mesh. */
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ double dist=0.0;
+
+ Vector_Sub( tmp, point, mesh->nodeCoord[eltNodes[eltNode_i]] );
+ dist = Vector_Mag( tmp );
+
+ if( dist < minDist ) {
+ minDist = dist;
+ minNode = eltNodes[eltNode_i];
+ }
+ }
+
+ return minNode;
+}
+
+/*
+** Determine if 'point' is inside the element corresponding to 'dElementInd'.
+*/
+
+Bool pointInElement( void* _context, Coord point, Element_DomainIndex dElementInd ) {
+ Snac_Context* context = (Snac_Context*)_context;
+ Mesh* mesh = context->mesh;
+ NodeLayout* nLayout = mesh->layout->nodeLayout;
+ unsigned nEltNodes;
+ Node_DomainIndex* eltNodes;
+ Coord crds[8];
+ double bc[4];
+ unsigned inds[4];
+ unsigned eltNode_i;
+
+ /* Extract the element's nodes, of which there should be eight. */
+ {
+ Element_GlobalIndex gEltInd;
+
+ nEltNodes = 8;
+ eltNodes = Memory_Alloc_Array( Node_DomainIndex, nEltNodes, "SnacRemesher" );
+ gEltInd = Mesh_ElementMapDomainToGlobal( mesh, dElementInd );
+ nLayout->buildElementNodes( nLayout, gEltInd, eltNodes );
+ }
+
+ /* Convert the node indices back to domain values. */
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ ) {
+ eltNodes[eltNode_i] = Mesh_NodeMapGlobalToDomain( mesh, eltNodes[eltNode_i] );
+ }
+
+ /* Copy coordinates. */
+ for( eltNode_i = 0; eltNode_i < nEltNodes; eltNode_i++ )
+ memcpy( crds[eltNode_i], mesh->nodeCoord[eltNodes[eltNode_i]], sizeof(Coord) );
+
+ if( _HexaEL_FindTetBarycenter( crds, point, bc, inds, INCLUSIVE_UPPER_BOUNDARY, NULL, 0 ) ) {
+ return True;
+ }
+
+ return False;
+
+#if 0
+
+ unsigned plane_i;
+
+
+ const unsigned planeInds[6][3] = { { 0, 4, 1 }, { 3, 2, 7 }, { 0, 3, 4 },
+ { 1, 5, 2 }, { 0, 1, 3 }, { 5, 4, 6 } };
+
+ /* As we are dealing with hexahedral meshes with Snac, there will be six planes to check. */
+ for( plane_i = 0; plane_i < 6; plane_i++ ) {
+ Coord norm;
+ double dist;
+
+ /* Build the plane normal. */
+ {
+ Node_DomainIndex inds[3];
+ Coord tmpA, tmpB;
+
+ inds[0] = eltNodes[planeInds[plane_i][0]];
+ inds[1] = eltNodes[planeInds[plane_i][1]];
+ inds[2] = eltNodes[planeInds[plane_i][2]];
+
+ Vector_Sub( tmpA, mesh->nodeCoord[inds[1]], mesh->nodeCoord[inds[0]] );
+ Vector_Sub( tmpB, mesh->nodeCoord[inds[2]], mesh->nodeCoord[inds[0]] );
+ Vector_Cross( norm, tmpA, tmpB );
+ Vector_Norm( norm, norm );
+ }
+
+ /* Calc distance. */
+ dist = Vector_Dot( norm, mesh->nodeCoord[planeInds[plane_i][0]] );
+
+ /* Check which side of the plane our new point is. */
+ if( Vector_Dot( norm, point ) <= dist ) {
+ /* It is inside, so we may continue. */
+ continue;
+ }
+ else {
+ /* It's outside, so this is the wrong element. */
+ break;
+ }
+ }
+
+ /* Free the element nodes array. */
+ FreeArray( eltNodes );
+
+ /* Return appropriately. */
+
+ return (plane_i < 6) ? False : True;
+#endif
+}
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/Utils.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,58 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+**
+** Comments:
+**
+** $Id: Utils.h 1848 2004-08-11 07:10:08Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_Utils_h__
+#define __SnacRemesher_Utils_h__
+
+
+ #define SnacArcTan( o, a ) \
+ (((a) == 0.0) ? 0.5 * M_PI : \
+ ((a) > 0.0) ? atan( (o) / (a) ) : \
+ ((o) >= 0.0) ? M_PI + atan( (o) / (a) ) : \
+ atan( (o) / (a) ) - M_PI)
+
+
+ Node_DomainIndex findClosestNode( void* _context, Coord point, Node_LocalIndex refNodeInd );
+
+ Node_DomainIndex findClosestNodeInElement( void* _context, Coord point, unsigned nEltNodes, Node_DomainIndex *eltNodes );
+
+ Bool pointInElement( void* _context, Coord point, Element_DomainIndex dElementInd );
+
+
+#endif /* __SnacRemesher_Utils_h__ */
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/makefile
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/makefile (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/makefile 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,53 @@
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+##
+## Copyright (C), 2003,
+## Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+## Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+## University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+##
+## Authors:
+## Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+## Stevan M. Quenette, Visitor in Geophysics, Caltech.
+## Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+## Luc Lavier, Research Scientist, Caltech.
+##
+## 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## $Id: makefile 3049 2005-06-22 07:46:15Z AlanLo $
+##
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# obtain defaults for required variables according to system and project location, and then run the build.
+ifndef PROJ_ROOT
+ PROJ_ROOT=../..
+endif
+include ${PROJ_ROOT}/Makefile.system
+
+include Makefile.def
+
+mod = ${def_mod}
+includes = ${def_inc}
+
+SRCS = ${def_srcs}
+
+HDRS = ${def_hdrs}
+
+PROJ_LIBS = ${def_libs}
+EXTERNAL_LIBS = -L${STGERMAIN_LIBDIR} -lSnac -lStGermain
+EXTERNAL_INCLUDES = -I${STGERMAIN_INCDIR}/StGermain -I${STGERMAIN_INCDIR}
+
+packages = MPI XML MATH GSL
+
+include ${PROJ_ROOT}/Makefile.vmake
Added: long/3D/SNAC/trunk/Snac/plugins/remesher_BI/types.h
===================================================================
--- long/3D/SNAC/trunk/Snac/plugins/remesher_BI/types.h (rev 0)
+++ long/3D/SNAC/trunk/Snac/plugins/remesher_BI/types.h 2011-10-07 16:18:20 UTC (rev 19040)
@@ -0,0 +1,52 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003,
+** Steve Quenette, 110 Victoria Street, Melbourne, Victoria, 3053, Australia.
+** Californian Institute of Technology, 1200 East California Boulevard, Pasadena, California, 91125, USA.
+** University of Texas, 1 University Station, Austin, Texas, 78712, USA.
+**
+** Authors:
+** Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+** Stevan M. Quenette, Visitor in Geophysics, Caltech.
+** Luc Lavier, Research Scientist, The University of Texas. (luc at utig.ug.utexas.edu)
+** Luc Lavier, Research Scientist, Caltech.
+**
+** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+**
+*/
+/** \file
+** Role:
+**
+** Assumptions:
+** None as yet.
+**
+** Comments:
+** None as yet.
+**
+** $Id: types.h 1581 2004-07-02 14:39:36Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#ifndef __SnacRemesher_types_h__
+#define __SnacRemesher_types_h__
+
+ /* Plastic */
+ typedef struct _SnacRemesher_Context SnacRemesher_Context;
+ typedef struct _SnacRemesher_Element SnacRemesher_Element;
+ typedef struct _SnacRemesher_Node SnacRemesher_Node;
+ typedef struct _SnacRemesher_Mesh SnacRemesher_Mesh;
+ typedef struct _SnacRemesher_EntryPoint SnacRemesher_EntryPoint;
+
+#endif /* __SnacRemesher_types_h__ */
More information about the CIG-COMMITS
mailing list