00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <mpi.h>
00026 #include <StGermain/StGermain.h>
00027 #include "SPModel/SPModel.h"
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <assert.h>
00031
00032
00033 #include "FaultModel.h"
00034
00035
00036 const Type SPModelFaultModel_Type = "SPModelFaultModel";
00037 ExtensionInfo_Index SPModel_FaultModel_ContextExtHandle;
00038 ExtensionInfo_Index SPModel_Simulation_ContextExtHandle;
00039
00040 void* _SPModelFaultModel_DefaultNew( Name name ) {
00041 return Codelet_New(
00042 SPModelFaultModel_Type,
00043 _SPModelFaultModel_DefaultNew,
00044 _SPModelFaultModel_Construct,
00045 _Codelet_Build,
00046 _Codelet_Initialise,
00047 _Codelet_Execute,
00048 _Codelet_Destroy,
00049 name );
00050 }
00051
00052 void _SPModelFaultModel_Construct( void* component, Stg_ComponentFactory* data ) {
00053 SPModel_Context* context;
00054
00055 context = (SPModel_Context*)Stg_ComponentFactory_ConstructByName( data, "context", SPModel_Context, True );
00056
00057 SPModel_FaultModel_ContextExtHandle = ExtensionManager_Add( context->extensionMgr, "FaultModel",
00058 sizeof(SPModelFaultModelContextExtension) );
00059
00060 SPModel_Simulation_ContextExtHandle = ExtensionManager_GetHandle( context->extensionMgr, "Simulation" );
00061
00062 _SPModelFaultModel_Init( context );
00063
00064 Journal_DPrintf( context->debug, "In %s():\n", __func__ );
00065 ContextEP_Append( context, AbstractContext_EP_Solve, SPModelFaultModel_Solve );
00066 }
00067
00068 #define EPSILON 1e-06
00069 int colinearityCheck( Coord a, Coord b, Coord c )
00070 {
00071 Coord ab;
00072 Coord ac;
00073
00074 StGermain_VectorSubtraction( ab, b, a, 3 );
00075 StGermain_VectorSubtraction( ac, c, a, 3 );
00076
00077 StGermain_VectorNormalise( ab, 3 );
00078 StGermain_VectorNormalise( ac, 3 );
00079
00080
00081 if( (1.0f - fabs(StGermain_VectorDotProduct( ab, ac, 3 ))) < EPSILON ){
00082 return 1;
00083 }
00084 else{
00085 return 0;
00086 }
00087 }
00088
00089 void _SPModelFaultModel_Init( void* _context ) {
00090 SPModel_Context *context = NULL;
00091 SPModelFaultModelContextExtension *faultModel = NULL;
00092 Dictionary *dict = NULL, *subDict = NULL;
00093 Dictionary_Entry *subDictEntry = NULL;
00094 FILE *f;
00095 char *fileName = NULL;
00096 int i = 0, j = 0;
00097 char buffer[512] = { 0 };
00098 Coord midChord1, midChord2;
00099 Coord direcChord1, direcChord2;
00100 Coord cp1, cp2;
00101 Coord rhs, lhs;
00102 Coord nodeCoord;
00103 double temp = 0.0f, lambda = 0.0f;
00104 SurfaceMesh *mesh = NULL;
00105
00106 context = (SPModel_Context*)_context;
00107 assert( context );
00108
00109 faultModel = (SPModelFaultModelContextExtension*)ExtensionManager_Get
00110 ( context->extensionMgr, context, SPModel_FaultModel_ContextExtHandle );
00111 assert( faultModel );
00112
00113 mesh = context->localMesh;
00114 assert( mesh );
00115
00116 dict = Dictionary_Entry_Value_AsDictionary( Dictionary_Get( context->dictionary, "faultModel" ) );
00117
00118 if( dict ){
00119
00120 faultModel->numFaultModel = Dictionary_GetCount( dict );
00121
00122 faultModel->coordType = Memory_Alloc_Array_Unnamed( CoordinateType, faultModel->numFaultModel );
00123 faultModel->arcPoints = Memory_Alloc_2DArray_Unnamed( Coord, faultModel->numFaultModel, 4);
00124 faultModel->arcs = Memory_Alloc_2DArray_Unnamed( Arc, faultModel->numFaultModel, 2 );
00125 faultModel->circleCentrePoints = Memory_Alloc_2DArray_Unnamed( Coord, faultModel->numFaultModel, 2 );
00126 faultModel->radiusSq = Memory_Alloc_2DArray_Unnamed( double, faultModel->numFaultModel, 2 );
00127 faultModel->faultBounds = Memory_Alloc_Array_Unnamed( int, faultModel->numFaultModel );
00128
00129 for( i=0; i<faultModel->numFaultModel; i++ ){
00130
00131 subDictEntry = dict->entryPtr[ i ];
00132 subDict = Dictionary_Entry_Value_AsDictionary( subDictEntry->value );
00133
00134 assert( subDict );
00135
00136 fileName = Dictionary_GetString( subDict, "faultModelBoundaryFile" );
00137 f = fopen( fileName, "r+" );
00138
00139 if( f ){
00140
00141 memset( buffer, 0, sizeof( buffer ) );
00142
00143 fgets( buffer, sizeof( buffer ), f );
00144 if( strcasecmp(buffer, "NORMALISED\n") == 0 ){
00145 faultModel->coordType[i] = NORMALISED;
00146 }
00147 else if( strcasecmp(buffer, "NATURAL\n") == 0 ){
00148 faultModel->coordType[i] = NATURAL;
00149 }
00150 else{
00151 Journal_Printf( context->info, "Error in file `%s`\n", fileName );
00152 exit( EXIT_FAILURE );
00153 }
00154
00155 fscanf( f, "%d", &(faultModel->faultBounds[i]) );
00156
00157 for( j=0; j<4; j++ ){
00158 fscanf( f, "%lf %lf", &(faultModel->arcPoints[i][j][0]), &(faultModel->arcPoints[i][j][1]) );
00159 }
00160
00161 for( j=0; j<2; j++ ){
00162 fscanf( f, "%d %d %d", &(faultModel->arcs[i][j].index[0]), &(faultModel->arcs[i][j].index[1]),
00163 &(faultModel->arcs[i][j].index[2]) );
00164
00165 faultModel->arcs[i][j].index[0] -= 1;
00166 faultModel->arcs[i][j].index[1] -= 1;
00167 faultModel->arcs[i][j].index[2] -= 1;
00168 }
00169 fclose( f );
00170 }
00171 else{
00172 Journal_Printf( context->info, "Error opening file `%s`..!\n", fileName );
00173 exit( EXIT_FAILURE );
00174 }
00175 }
00176
00177 #if 0
00178 printf( (faultModel->coordType==NORMALISED)?"normalised\n":"natural\n" );
00179 printf( "%d\n", faultModel->numFaultModel );
00180 for( i=0; i<faultModel->numFaultModel; i++ ){
00181 for( j=0; j<4; j++ ){
00182 printf( "%lf %lf\n", faultModel->arcPoints[i][j][0], faultModel->arcPoints[i][j][1] );
00183 }
00184 printf( "%d %d %d\n", faultModel->arcs[i][0].index[0], faultModel->arcs[i][0].index[1],
00185 faultModel->arcs[i][0].index[2] );
00186 printf( "%d %d %d\n", faultModel->arcs[i][1].index[0], faultModel->arcs[i][1].index[1],
00187 faultModel->arcs[i][1].index[2] );
00188 printf( "\n\n" );
00189 }
00190 #endif
00191
00192
00193 for( i=0; i<faultModel->numFaultModel; i++ ){
00194 for( j=0; j<2; j++ ){
00195 if( colinearityCheck( faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]],
00196 faultModel->arcPoints[i][faultModel->arcs[i][j].index[1]],
00197 faultModel->arcPoints[i][faultModel->arcs[i][j].index[2]]) ){
00198 Journal_Printf( context->info, "Arc points for faultModel %d are colinear..!\n", i+1 );
00199 exit( EXIT_FAILURE );
00200 }
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 faultModel->nodeIndices = Memory_Alloc_2DArray_Unnamed( int, faultModel->numFaultModel, mesh->myLoad );
00220 faultModel->distFromBoundary = Memory_Alloc_2DArray_Unnamed( double, faultModel->numFaultModel, mesh->myLoad );
00221
00222 for( i=0; i<faultModel->numFaultModel; i++ ){
00223
00224 for( j=0; j<2; j++ ){
00225
00226 memset( midChord1, 0, sizeof(Coord) );
00227 midChord1[0] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][0] +
00228 faultModel->arcPoints[i][faultModel->arcs[i][j].index[1]][0]) / 2.0f;
00229 midChord1[1] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][1] +
00230 faultModel->arcPoints[i][faultModel->arcs[i][j].index[1]][1]) / 2.0f;
00231
00232 memset( midChord2, 0, sizeof(Coord) );
00233 midChord2[0] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][0] +
00234 faultModel->arcPoints[i][faultModel->arcs[i][j].index[2]][0]) / 2.0f;
00235 midChord2[1] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][1] +
00236 faultModel->arcPoints[i][faultModel->arcs[i][j].index[2]][1]) / 2.0f;
00237
00238 memset( direcChord1, 0, sizeof( Coord ) );
00239 direcChord1[0] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[1]][0] -
00240 faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][0] );
00241 direcChord1[1] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[1]][1] -
00242 faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][1] );
00243
00244 memset( direcChord2, 0, sizeof( Coord ) );
00245 direcChord2[0] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[2]][0] -
00246 faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][0] );
00247 direcChord2[1] = (faultModel->arcPoints[i][faultModel->arcs[i][j].index[2]][1] -
00248 faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]][1] );
00249
00250 StGermain_VectorNormalise( direcChord1, 3 );
00251 StGermain_VectorNormalise( direcChord2, 3 );
00252
00253
00254 temp = direcChord1[0];
00255 direcChord1[0] = -direcChord1[1];
00256 direcChord1[1] = temp;
00257
00258 temp = direcChord2[0];
00259 direcChord2[0] = -direcChord2[1];
00260 direcChord2[1] = temp;
00261
00262 StGermain_VectorCrossProduct( cp1, midChord1, direcChord2 );
00263 StGermain_VectorCrossProduct( cp2, midChord2, direcChord2 );
00264 StGermain_VectorSubtraction( rhs, cp2, cp1, 3 );
00265
00266 StGermain_VectorCrossProduct( cp2, direcChord1, direcChord2 );
00267
00268 memcpy( lhs, cp2, sizeof( Coord ) );
00269 lambda = rhs[2] / lhs[2];
00270
00271 faultModel->circleCentrePoints[i][j][0] = midChord1[0] + direcChord1[0]*lambda;
00272 faultModel->circleCentrePoints[i][j][1] = midChord1[1] + direcChord1[1]*lambda;
00273 faultModel->circleCentrePoints[i][j][2] = 0;
00274
00275
00276 faultModel->radiusSq[i][j] = pow( StGermain_DistanceBetweenPoints(
00277 faultModel->arcPoints[i][faultModel->arcs[i][j].index[0]],
00278 faultModel->circleCentrePoints[i][j], 3), 2.0f);
00279
00280
00281
00282
00283
00284 }
00285 }
00286
00287 for( i=0; i<faultModel->numFaultModel; i++ ){
00288 for( j=0; j<2; j++ ){
00289 if( faultModel->coordType[i] == NORMALISED ){
00290 faultModel->circleCentrePoints[i][j][0] *= mesh->sideX;
00291 faultModel->circleCentrePoints[i][j][1] *= mesh->sideY;
00292
00293 faultModel->radiusSq[i][j] *= (mesh->sideX * mesh->sideY);
00294 }
00295 }
00296
00297 switch( faultModel->faultBounds[i] ){
00298
00299 case 1:
00300 {
00301 for( j=0; j<mesh->myLoad; j++ ){
00302 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][0][0], 2.0f ) +
00303 pow( mesh->y[j] - faultModel->circleCentrePoints[i][0][1], 2.0f );
00304
00305 faultModel->nodeIndices[i][j] = UNDEFINED;
00306 if( temp > faultModel->radiusSq[i][0] ){
00307 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][1][0], 2.0f ) +
00308 pow( mesh->y[j] - faultModel->circleCentrePoints[i][1][1], 2.0f );
00309
00310 if( temp < faultModel->radiusSq[i][1] ){
00311 faultModel->nodeIndices[i][j] = mesh->id[j];
00312 }
00313 }
00314 }
00315 }
00316 break;
00317
00318 case 2:
00319 {
00320 for( j=0; j<mesh->myLoad; j++ ){
00321 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][0][0], 2.0f ) +
00322 pow( mesh->y[j] - faultModel->circleCentrePoints[i][0][1], 2.0f );
00323
00324 faultModel->nodeIndices[i][j] = UNDEFINED;
00325 if( temp < faultModel->radiusSq[i][0] ){
00326 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][1][0], 2.0f ) +
00327 pow( mesh->y[j] - faultModel->circleCentrePoints[i][1][1], 2.0f );
00328
00329 if( temp < faultModel->radiusSq[i][1] ){
00330 faultModel->nodeIndices[i][j] = mesh->id[j];
00331 }
00332 }
00333 }
00334 }
00335 break;
00336
00337 default:
00338 {
00339 }
00340 break;
00341 }
00342
00343
00344 if( StGermain_DistanceBetweenPoints( faultModel->circleCentrePoints[i][0],
00345 faultModel->circleCentrePoints[i][1], 3 ) + faultModel->radiusSq[i][1] <=
00346 sqrt( faultModel->radiusSq[i][0] ) ){
00347
00348 Journal_Printf( context->info, "Circle 2 inside circle 1 in faultModel %d..!\n", i+1 );
00349 exit( EXIT_FAILURE );
00350 }
00351
00352 for( j=0; j<mesh->myLoad; j++ ){
00353 if( faultModel->nodeIndices[i][j] != UNDEFINED ){
00354 nodeCoord[0] = mesh->x[mesh->mapGlobalToLocal[faultModel->nodeIndices[i][j]-1]];
00355 nodeCoord[1] = mesh->y[mesh->mapGlobalToLocal[faultModel->nodeIndices[i][j]-1]];
00356 nodeCoord[2] = 0;
00357 faultModel->distFromBoundary[i][j] = (sqrt(faultModel->radiusSq[i][1]) -
00358 StGermain_DistanceBetweenPoints( nodeCoord, faultModel->circleCentrePoints[i][1], 3 )) /
00359 ( sqrt(faultModel->radiusSq[i][0]) - (sqrt(faultModel->radiusSq[i][0]) - sqrt(faultModel->radiusSq[i][1])) );
00360 }
00361 }
00362 }
00363
00364 faultModel->fmUpliftRate = (ParameterTimeSeries**) malloc( sizeof( void* ) * faultModel->numFaultModel );
00365
00366 for( i=0; i<faultModel->numFaultModel; i++ ){
00367 subDictEntry = dict->entryPtr[ i ];
00368 subDict = Dictionary_Entry_Value_AsDictionary( subDictEntry->value );
00369
00370 assert( subDict );
00371
00372 faultModel->fmUpliftRate[i] = ParameterTimeSeries_New( "faultModelUpliftRate", 0.0f, subDict );
00373 Stg_Component_Build( faultModel->fmUpliftRate[i], NULL, False );
00374 }
00375 }
00376 else{
00377 Journal_Printf( context->info, "faultModel struct not found in xml file..!\n" );
00378 exit( EXIT_FAILURE );
00379 }
00380 }
00381
00382 void SPModelFaultModel_RefreshNodeIndices( void *_context )
00383 {
00384 SPModel_Context *context = (SPModel_Context*)_context;
00385 SurfaceMesh *mesh = NULL;
00386 SPModelFaultModelContextExtension *faultModel = NULL;
00387 int i = 0, j = 0;
00388 float temp = 0;
00389 Coord nodeCoord;
00390
00391 assert( context );
00392
00393 faultModel = (SPModelFaultModelContextExtension*)ExtensionManager_Get
00394 ( context->extensionMgr, context, SPModel_FaultModel_ContextExtHandle );
00395 assert( faultModel );
00396
00397 mesh = context->localMesh;
00398 assert( mesh );
00399
00400 Memory_Free( faultModel->nodeIndices );
00401 Memory_Free( faultModel->distFromBoundary );
00402
00403 faultModel->nodeIndices = Memory_Alloc_2DArray_Unnamed( int, faultModel->numFaultModel, mesh->myLoad );
00404 faultModel->distFromBoundary = Memory_Alloc_2DArray_Unnamed( double, faultModel->numFaultModel, mesh->myLoad );
00405
00406 for( i=0; i<faultModel->numFaultModel; i++ ){
00407 for( j=0; j<mesh->myLoad; j++ ){
00408 faultModel->nodeIndices[i][j] = UNDEFINED;
00409 }
00410 }
00411
00412 for( i=0; i<faultModel->numFaultModel; i++ ){
00413 switch( faultModel->faultBounds[i] ){
00414
00415 case 1:
00416 {
00417 for( j=0; j<mesh->myLoad; j++ ){
00418 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][0][0], 2.0f ) +
00419 pow( mesh->y[j] - faultModel->circleCentrePoints[i][0][1], 2.0f );
00420
00421 faultModel->nodeIndices[i][j] = UNDEFINED;
00422 if( temp > faultModel->radiusSq[i][0] ){
00423 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][1][0], 2.0f ) +
00424 pow( mesh->y[j] - faultModel->circleCentrePoints[i][1][1], 2.0f );
00425
00426 if( temp < faultModel->radiusSq[i][1] ){
00427 faultModel->nodeIndices[i][j] = mesh->id[j];
00428 }
00429 }
00430 }
00431 }
00432 break;
00433
00434 case 2:
00435 {
00436 for( j=0; j<mesh->myLoad; j++ ){
00437 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][0][0], 2.0f ) +
00438 pow( mesh->y[j] - faultModel->circleCentrePoints[i][0][1], 2.0f );
00439
00440 faultModel->nodeIndices[i][j] = UNDEFINED;
00441 if( temp < faultModel->radiusSq[i][0] ){
00442 temp = pow( mesh->x[j] - faultModel->circleCentrePoints[i][1][0], 2.0f ) +
00443 pow( mesh->y[j] - faultModel->circleCentrePoints[i][1][1], 2.0f );
00444
00445 if( temp < faultModel->radiusSq[i][1] ){
00446 faultModel->nodeIndices[i][j] = mesh->id[j];
00447 }
00448 }
00449 }
00450 }
00451 break;
00452
00453 default:
00454 {
00455 }
00456 break;
00457 }
00458
00459 for( j=0; j<mesh->myLoad; j++ ){
00460 if( faultModel->nodeIndices[i][j] != UNDEFINED ){
00461 nodeCoord[0] = mesh->x[mesh->mapGlobalToLocal[faultModel->nodeIndices[i][j]-1]];
00462 nodeCoord[1] = mesh->y[mesh->mapGlobalToLocal[faultModel->nodeIndices[i][j]-1]];
00463 nodeCoord[2] = 0;
00464 faultModel->distFromBoundary[i][j] = (sqrt(faultModel->radiusSq[i][1]) -
00465 StGermain_DistanceBetweenPoints( nodeCoord, faultModel->circleCentrePoints[i][1], 3 )) /
00466 ( sqrt(faultModel->radiusSq[i][0]) - (sqrt(faultModel->radiusSq[i][0]) - sqrt(faultModel->radiusSq[i][1])) );
00467 }
00468 }
00469 }
00470 }
00471
00472 void SPModelFaultModel_Solve( void *_context ) {
00473 SPModel_Context *context = (SPModel_Context*)_context;
00474 SurfaceMesh *mesh = NULL;
00475 SPModelFaultModelContextExtension *faultModel = NULL;
00476 SPModelSimulationContextExtension *simulationExt = NULL;
00477 int i = 0, j = 0, localIndex = 0;
00478
00479 assert( context );
00480
00481 faultModel = (SPModelFaultModelContextExtension*)ExtensionManager_Get
00482 ( context->extensionMgr, context, SPModel_FaultModel_ContextExtHandle );
00483 simulationExt = (SPModelSimulationContextExtension*)ExtensionManager_Get
00484 ( context->extensionMgr, context, SPModel_Simulation_ContextExtHandle );
00485
00486 assert( faultModel );
00487 assert( simulationExt );
00488
00489 mesh = context->localMesh;
00490 assert( mesh );
00491
00492
00493 if( context->redistributeNodesFlag ){
00494 SPModelFaultModel_RefreshNodeIndices( _context );
00495
00496 }
00497
00498 for( i=0; i<faultModel->numFaultModel; i++ ){
00499 ParameterTimeSeries_Interpolate( faultModel->fmUpliftRate[i], context );
00500 for( j=0; j<mesh->myLoad; j++ ){
00501 if( faultModel->nodeIndices[i][j] != UNDEFINED ){
00502 localIndex = mesh->mapGlobalToLocal[faultModel->nodeIndices[i][j]-1];
00503 assert( localIndex != mesh->myLoad );
00504 mesh->h[localIndex] += faultModel->fmUpliftRate[i]->value * faultModel->distFromBoundary[i][j];
00505
00506 simulationExt->uplift[localIndex] += faultModel->fmUpliftRate[i]->value * faultModel->distFromBoundary[i][j];
00507 }
00508 }
00509 }
00510 }
00511
00512 Index SPModelFaultModel_Register( PluginsManager* pluginsManager ) {
00513 return PluginsManager_Submit( pluginsManager, SPModelFaultModel_Type, "0", _SPModelFaultModel_DefaultNew );
00514 }
00515