comparison +scheme/ViscoElastic2d.m @ 1313:a4c8bf2371f3 feature/poroelastic

Add viscoelastic fault interface
author Martin Almquist <malmquist@stanford.edu>
date Wed, 22 Jul 2020 15:35:25 -0700
parents 6d64b57caf46
children 58df4a35fe43
comparison
equal deleted inserted replaced
1312:6d64b57caf46 1313:a4c8bf2371f3
409 function [closure, penalty] = interfaceFrictionalFault(obj,boundary,neighbour_scheme,neighbour_boundary,type) 409 function [closure, penalty] = interfaceFrictionalFault(obj,boundary,neighbour_scheme,neighbour_boundary,type)
410 tuning = type.tuning; 410 tuning = type.tuning;
411 411
412 % u denotes the solution in the own domain 412 % u denotes the solution in the own domain
413 % v denotes the solution in the neighbour domain 413 % v denotes the solution in the neighbour domain
414
415 u = obj; 414 u = obj;
416 v = neighbour_scheme; 415 v = neighbour_scheme;
417 416
418 % Operators, u side 417 dim = obj.dim;
419 e_u = u.getBoundaryOperatorForScalarField('e', boundary); 418
420 en_u = u.getBoundaryOperator('en', boundary); 419 n = u.getNormal(boundary);
421 tau_n_u = u.getBoundaryOperator('tau_n', boundary); 420 H_gamma = u.getBoundaryQuadratureForScalarField(boundary);
422 h11_u = u.getBorrowing(boundary); 421 e = u.getBoundaryOperatorForScalarField('e', boundary);
423 n_u = u.getNormal(boundary); 422
424 423 ev = v.getBoundaryOperatorForScalarField('e', neighbour_boundary);
425 C_u = u.C; 424
426 Ji_u = u.Ji; 425 H = u.H;
427 s_u = spdiag(u.(['s_' boundary])); 426 RHO = u.RHO;
428 m_tot_u = u.grid.N(); 427 ETA = u.ETA;
429 428 C = u.C;
430 % Operators, v side 429 Eu = u.Eu;
431 e_v = v.getBoundaryOperatorForScalarField('e', neighbour_boundary); 430 eU = u.eU;
432 en_v = v.getBoundaryOperator('en', neighbour_boundary); 431 eGamma = u.eGamma;
433 tau_n_v = v.getBoundaryOperator('tau_n', neighbour_boundary); 432 Egamma = u.Egamma;
434 h11_v = v.getBorrowing(neighbour_boundary); 433
435 n_v = v.getNormal(neighbour_boundary); 434 CV = v.C;
436 435 Ev = v.Eu;
437 C_v = v.C; 436 eV = v.eU;
438 Ji_v = v.Ji; 437 eGammaV = v.eGamma;
439 s_v = spdiag(v.(['s_' neighbour_boundary])); 438 nV = v.getNormal(neighbour_boundary);
440 m_tot_v = v.grid.N(); 439
441 440 % Reduce stiffness tensors to boundary size
442 % Operators that are only required for own domain 441 for i = 1:dim
443 Hi = u.E{1}*inv(u.H)*u.E{1}' + u.E{2}*inv(u.H)*u.E{2}'; 442 for j = 1:dim
444 RHOi = u.E{1}*inv(u.RHO)*u.E{1}' + u.E{2}*inv(u.RHO)*u.E{2}'; 443 for k = 1:dim
445 444 for l = 1:dim
446 % Shared operators 445 C{i,j,k,l} = e'*C{i,j,k,l}*e;
447 H_gamma = u.getBoundaryQuadratureForScalarField(boundary); 446 CV{i,j,k,l} = ev'*CV{i,j,k,l}*ev;
448 dim = u.dim; 447 end
449 448 end
450 % Preallocate 449 end
451 [~, m_int] = size(H_gamma); 450 end
452 closure = sparse(dim*m_tot_u, dim*m_tot_u); 451
453 penalty = sparse(dim*m_tot_u, dim*m_tot_v); 452 % Get elastic closure and penalty
454 453 [closure, penalty] = obj.elasticObj.interface(boundary, v.elasticObj, neighbour_boundary, type);
455 % Continuity of normal displacement, term 1: The symmetric term 454 closure = Eu*closure*Eu';
456 Z_u = sparse(m_int, m_int); 455 penalty = Eu*penalty*Ev';
457 Z_v = sparse(m_int, m_int);
458 for i = 1:dim
459 for j = 1:dim
460 for l = 1:dim
461 for k = 1:dim
462 Z_u = Z_u + n_u{i}*n_u{j}*e_u'*Ji_u*C_u{i,j,k,l}*e_u*n_u{k}*n_u{l};
463 Z_v = Z_v + n_v{i}*n_v{j}*e_v'*Ji_v*C_v{i,j,k,l}*e_v*n_v{k}*n_v{l};
464 end
465 end
466 end
467 end
468
469 Z = -tuning*dim*( 1/(4*h11_u)*s_u*Z_u + 1/(4*h11_v)*s_v*Z_v );
470 closure = closure + en_u*H_gamma*Z*en_u';
471 penalty = penalty + en_u*H_gamma*Z*en_v';
472
473 % Continuity of normal displacement, term 2: The symmetrizing term
474 closure = closure + 1/2*tau_n_u*H_gamma*en_u';
475 penalty = penalty + 1/2*tau_n_u*H_gamma*en_v';
476
477 % Continuity of normal traction
478 closure = closure - 1/2*en_u*H_gamma*tau_n_u';
479 penalty = penalty + 1/2*en_u*H_gamma*tau_n_v';
480
481 % Multiply all normal component terms by inverse of density x quadraure
482 closure = RHOi*Hi*closure;
483 penalty = RHOi*Hi*penalty;
484 456
485 % ---- Tangential tractions are imposed just like traction BC ------ 457 % ---- Tangential tractions are imposed just like traction BC ------
486 closure = closure + obj.boundary_condition(boundary, {'t', 't'}); 458 % We only need the viscous part
487 459 closure_tangential = obj.boundary_condition(boundary, {'t', 't'});
488 end 460 closure = closure + closure_tangential*Egamma*Egamma';
489 461
490 462
491 % Returns h11 for the boundary specified by the string boundary. 463 % ------ Coupling of normal component -----------
492 % op -- string 464 % Add viscous part of traction coupling
493 function h11 = getBorrowing(obj, boundary) 465 for i = 1:dim
494 assertIsMember(boundary, {'w', 'e', 's', 'n'}) 466 for j = 1:dim
495 467 for k = 1:dim
496 switch boundary 468 for l = 1:dim
497 case {'w','e'} 469 for m = 1:dim
498 h11 = obj.refObj.h11{1}; 470 closure = closure + 1/2*eU{m}*( (RHO*H)\(e*n{m}*H_gamma*n{j}*n{i}*C{i,j,k,l}*e'*eGamma{k,l}') );
499 case {'s', 'n'} 471 penalty = penalty - 1/2*eU{m}*( (RHO*H)\(e*n{m}*H_gamma*nV{j}*nV{i}*CV{i,j,k,l}*ev'*eGammaV{k,l}') );
500 h11 = obj.refObj.h11{2}; 472 end
501 end 473 end
474 end
475 end
476 end
477
478 % Add penalty to strain rate eq
479 for i = 1:dim
480 for j = 1:dim
481 for k = 1:dim
482 for l = 1:dim
483 for m = 1:dim
484 closure = closure - 1/2*eGamma{i,j}*( (H*ETA)\(e*n{l}*n{k}*C{i,j,k,l}*H_gamma*n{m}*e'*eU{m}') );
485 penalty = penalty - 1/2*eGamma{i,j}*( (H*ETA)\(e*n{l}*n{k}*C{i,j,k,l}*H_gamma*nV{m}*ev'*eV{m}') );
486 end
487 end
488 end
489 end
490 end
491 %-------------------------------------------------
492
502 end 493 end
503 494
504 % Returns the outward unit normal vector for the boundary specified by the string boundary. 495 % Returns the outward unit normal vector for the boundary specified by the string boundary.
505 % n is a cell of diagonal matrices for each normal component, n{1} = n_1, n{2} = n_2. 496 % n is a cell of diagonal matrices for each normal component, n{1} = n_1, n{2} = n_2.
506 function n = getNormal(obj, boundary) 497 function n = getNormal(obj, boundary)
521 % op -- string 512 % op -- string
522 function o = getBoundaryOperator(obj, op, boundary) 513 function o = getBoundaryOperator(obj, op, boundary)
523 assertIsMember(boundary, {'w', 'e', 's', 'n'}) 514 assertIsMember(boundary, {'w', 'e', 's', 'n'})
524 assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'en', 'et', 'tau_n', 'tau_t'}) 515 assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'en', 'et', 'tau_n', 'tau_t'})
525 516
526 o = obj.([op, '_', boundary]); 517 o = obj.elasticObj.([op, '_', boundary]);
527 518
528 end 519 end
529 520
530 % Returns the boundary operator op for the boundary specified by the string boundary. 521 % Returns the boundary operator op for the boundary specified by the string boundary.
531 % op -- string 522 % op -- string